标签云

微信群

扫码加入我们

WeChat QR Code

I've always wondered this - why can't you declare variables after a case label in a switch statement?In C++ you can declare variables pretty much anywhere (and declaring them close to first use is obviously a good thing) but the following still won't work:switch (val){case VAL:// This won't workint newVal = 42;break;case ANOTHER_VAL:...break;}The above gives me the following error (MSC):initialization of 'newVal' is skipped by 'case' labelThis seems to be a limitation in other languages too.Why is this such a problem?


For an explanation based on the C BNF grammar, seestackoverflow.com/questions/1180550/weird-switch-error-in-obj-c/…

2019年09月18日20分52秒

Here is a really good read about switch statements and labels (ABC:) in general.

2019年09月18日20分52秒

I would say 'Why can't variables be initialized in a switch statement rather than declared'.Since just declaring the variable give me only a warning in MSVC.

2019年09月18日20分52秒

Relative to opening a new scope - favor readability and consistency in the code. In the old days, you might have automatically got an "extra" stack frame, but now that should not be the case for any decent optimizing compiler.

2019年09月18日20分52秒

I agree with Jeff - it is all too easy to "assume" scope when reading a switch statement because of the indenting style that most people use. My own style is to always open a new scope for each case/default if it is more than one line long.

2019年09月18日20分52秒

workmad3 - Can you find me any C++ compiler at all that will generate a new stack frame if you don't declare any new variables?You worried me briefly, but none of G++ 3.1, Visual C++ 7 or Intel C++ 8 will generate any code for new scopes where you don't declare any variables.

2019年09月18日20分52秒

workmad3 by entering a new curly braces block doesn't cause a new stack frame stackoverflow.com/questions/2759371/…

2019年09月18日20分52秒

TallJef I don't know what 'old days' you're referring to. I have never encountered a compiler where all the stack space for a method isn't allocated when the method is entered, in 40 years.

2019年09月18日20分52秒

AnT: I understand why the one that fixes C++ isn't applicable for C; however, I'm unable to understand how it fixes the C++ issue of skipping the initialization in the first place? Wouldn't it still skip the declaration and assignment of newVal when it jumps to ANOTHER_VAL?

2019年09月18日20分52秒

legends2k: Yes, it still skips it. However, when I say "it fixes the issue" , I mean that it fixes the C++ compiler error. In C++ it is illegal to skip a scalar declaration with initializer, but it is perfectly fine to skip a scalar declaration without initializer. At case ANOTHER_VAL: point variable newVal is visible, but with indeterminate value.

2019年09月18日20分52秒

Fascinating. I found this question after reading §A9.3: Compound Statement from K&R C (second edition). The entry mentioned the technical definition of a compound-statement which is {declaration-list[opt] statement-list[opt]}. Confused, because I had thought a declaration WAS a statement, I looked it up and immediately found this question, an example where said disparity becomes apparent and actually breaks a program. I believe another solution (for C) would be to put another statement (possibly a null statement?) before the declaration so that the labeled-statement is satisfied.

2019年09月18日20分52秒

Oops, I just noticed that the null-statement solution I suggested is already in your answer. Never mind, then.

2019年09月19日20分52秒

The best solution is probably to just declare the variable outside of the switch statement.

2019年09月18日20分52秒

"Error jumping over initialization"??? Not with my GCC. It may give a "j may be used unitialized" warning when using j below label, but there is no error. However, in case of switch, there is an error (a hard error, not a weak warning).

2019年09月18日20分52秒

Mecki:It is illegal in C++.ISO C++ '03 - 6.7/3:"...A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5)."

2019年09月18日20分52秒

Yes, but it is not illegal in C (at least gcc says it's not). j will be uninitialized (have some random number), but the compiler compiles it. However, in case of the switch statement, the compiler won't even compile it and I fail to see the difference between a goto/label case and a switch case.

2019年09月18日20分52秒

Mecki:In general a single compiler behaviour does not necessarily reflect whtat is actually allowed by the language.I've checked both C'90 and C'99 and both standards include an example with a jump over initialization in a switch statement.

2019年09月18日20分52秒

You correctly described the C issue. But the assertion that in C++ labelled initialization is not allowed is completely not true. There's nothing wrong with labeled initialization in C++. What C++ does not allow is jumping over initialization of variable a into the scope of variable a. So, from C point of view, the problems is with case VAL: label and you described it correctly. But from C++ point of view, the problem is with case ANOTHER_VAL: label.

2019年09月18日20分52秒

In C++, unlike in C, declarations are a subset of statements.

2019年09月18日20分52秒

This Duff's device implementation has a bug that makes it extremely slow: count is type int so the % must perform a real division/modulo operation. Make count unsigned (or better yet, always use size_t for counts/indices) and the problem goes away.

2019年09月19日20分52秒

R..: What?! In a two's complement system, signedness doesn't affect modulos by powers of 2 (it's just an AND on the bottom bits), and doesn't affect divisions by powers of 2 as long as your processor architecture has an arithmetic right-shift operation (SAR in x86, versus SHR which is for unsigned shifts).

2019年09月18日20分52秒

Chris: I believe he means when the compiler must allow for negative values where "just an AND on the bottom bits" doesn't hold; for example, -1 % 8 gives -1 on this two's complement system using g++ (the sign in this case is implementation defined per 5.6/4).

2019年09月18日20分52秒

Chris: I agree with you that R is exaggerating the impact; I only saw your comment and knew a simple AND didn't suffice.

2019年09月18日20分52秒

Also worth noting is the original Wikipedia code is for sending data to a memory mapped output, which looks odd here because it's not mentioned and every byte is copied to the same "to" location. Could get around that by either adding postfix ++ to the to, or mentioning the use case is for memory mapped IO. Totally peripheral to the original question :-).

2019年09月18日20分52秒

codepad.org/rTAActCN see here declaration is also not going to compile..

2019年09月18日20分52秒

Mr. 32 you have misunderstood what your error is: yes that's not going to compile but not because you're declaring a variable inside a switch.The error is because you're trying to declare a variable after a statement, which is illegal in C.

2019年09月18日20分52秒

Now a days that is legal in c90 and newer version of c

2019年09月18日20分52秒

Why would you do this?

2019年09月18日20分52秒

Very nice. Example of why: case 0 and case 1 might for instance initializing a variable differently that is then used in case 2.

2019年09月19日20分52秒

If you want both case 0 and case 1 to fall through case 2. ( without case 0 falling through case 1 ). Don't know if it's really useful, but sure works.

2019年09月19日20分52秒

You can just jump to the required label with goto without obfuscation of the code

2019年09月18日20分52秒

The variable can be declared, but it cannot be initialized.Also, I'm pretty sure that the issue does not relate in anyway to the stack and local variables.

2019年09月18日20分52秒

-1 here int x wil be never executed. see this codepad.org/PA1quYX3

2019年09月18日20分52秒

Mr.32 : actually your example shows that a printf is not executed, but in this case, the int x is not a statement but a declaration, the x is declared, space for it is reserved every time the function environment gets stacked, see: codepad.org/4E9Zuz1e

1970年01月01日00分03秒

I was expecting to find this when reading the title of the question, because the question is not about declaring variables within "case:" labels, but in switch statements. And only you (and VictorH, emphasising your answer) actually talked about variables in switch statements.

2019年09月18日20分52秒

The variable can be declared, but it cannot be initialized.

2019年09月18日20分52秒

Richard CordenI am confident that initialization will work.Do you still assert it cannot be initialized?

2019年09月18日20分52秒

-1 here int newVal = 42; wil be never executed. see this codepad.org/PA1quYX3

2019年09月18日20分52秒

the declaration int newVal will be executed, but not the = 42 assignment.

2019年09月18日20分52秒

The second example is NOT valid C++(test with vc2010 and gcc4.6.1 C++ not allow skip the initialization part. gcc error message is : cross initialization of 'int i'

2019年09月18日20分52秒

First is not fine on gcc 4.2: "error: expected expression before 'int'". As Peter and Mr.32 say, "case 0: ; int j; ..." and "case 0: ; int j = 7; ..." do both work. The problem in C is just that "case <label>: declaration" is not valid C syntax.

2019年09月19日20分52秒

If you're going to vote it down please explain why. I'm curious to know why creating an anonymous object appears to be an exemption.

2019年09月19日20分52秒

not a DV, but: The whole question is about declaring/scope of named variables. A temporary ("anonymous object" isn't a term) isn't a named variable, nor is it a declaration, nor is it subject to scope (unless bound to a const reference with scope of its own). It's an expression that lives and dies within its statement (wherever that may be). Therefore, it's wholly irrelevant.

2019年09月18日20分52秒

Foo(); is not a declaration; the question is about declarations.

2019年09月18日20分52秒