I've read this question about the "jump to case label" error, but I still have some questions. I'm using g++ 4.7 on Ubuntu 12.04.
This code gives an error:
int main() {
int foo = 1;
switch(foo) {
case 1:
int i = 0;
i++;
break;
case 2:
i++;
break;
}
}
The error is
jump-to-case-label.cpp: In function ‘int main()’:
jump-to-case-label.cpp:8:8: error: jump to case label [-fpermissive]
jump-to-case-label.cpp:5:9: error: crosses initialization of ‘int i’
However, this code compiles fine,
int main() {
int foo = 1;
switch(foo) {
case 1:
int i;
i = 0;
i++;
break;
case 2:
i++;
break;
}
}
Is the second code any less dangerous than the first? I'm confused as to why g++ allows it.
Secondly, the fix for this problem is to scope the initialized variable. If the initialized variable is a large object, and the switch statement is in a while loop, won't the constructor and destructor be called each time that scope is entered and left, causing a decrease in efficiency? Or will the compiler optimize this away?
Jumping past the initialization of an object, even if the object is of type int
, is always undefined behavior. Note, that the switch
-statement's statement isn't anything special: It is just a statement and people have [ab-]used this interesting ways, e.g., for Duff's Device. The only thing which is special within the statement is that labels can take the form default:
and case <const-integer-expr>:
.
The statement int i;
is a definition of the variable but no initialization. Thus, no initialization of a variable is by-passed. There is no bigger problem jumping past this definition than there is in the first place. Of course, the value gets assigned when jumping to case 1:
and not when jumping to case 2:
but this is no different than what happens in code outside of switch
-statements if people only define variables.
At first, compiler decides how it will open switch
to assembly code. May be if
or may be table as goto
. Also, if you write variable initialization together declaration, compiler says you that this is error
. In another cases it will be warning
(compiler warns you, but does not resist you). So, you can protect yourself. Just it tunes compiler options, where warnings
it will be errors
.
And to work correctly with variables in the switch
, you must specify their scope. For example:
switch(i)
{
case 1:
{
int j = 0;
}
break;
}
PS. For c++, switch is hell.
From C++11:
C.1.5 Clause 6: statements
6.4.2, 6.6.4 (switch and goto statements)
Change: It is now invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered)
Rationale: Constructors used in initializers may allocate resources which need to be de-allocated upon leaving the block. Allowing jump past initializers would require complicated run-time determination of allocation. Furthermore, any use of the uninitialized object could be a disaster. With this simple compile-time rule, C++ assures that if an initialized variable is in scope, then it has assuredly been initialized.
Effect on original feature: Deletion of semantically well-defined feature.
From gcc diagnostic pragmas:
6.57.10 Diagnostic Pragmas Diagnostic Pragmas
GCC allows the user to selectively enable or disable certain types of diagnostics, and change the kind of the diagnostic. For example, a project's policy might require that all sources compile with -Werror but certain files might have exceptions allowing specific types of warnings. Or, a project might selectively enable diagnostics and treat them as errors depending on which preprocessor macros are defined.
PSS. Compiler knows that into the chunk of code your variable uninitialized. Whatever it been static C/C++ analysis
(For example, for free cppcheck
) show you problem place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With