"crosses variable initialization" only when initialized in conjunction with a declaration

I have read this "transition to case" error question , but I still have some questions. I am 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; } } 

Error

 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 less dangerous than the first? I am confused why g ++ allows this.

Secondly, the fix for this problem is to span the initialized variable. If the initialized variable is a large object, and the switch statement is in the while loop, will the constructor and destructor be called every time the input area is entered and left, which leads to a decrease in efficiency? Or does the compiler optimize this?

+4
source share
3 answers

Jumping past the initialization of an object, even if the object is of type int , always works undefined. Note that the switch -statement switch is not something special: it is just an expression, and people [ab-] used this interesting way, for example, for the Duff device . The only thing special about the application is that labels can take the form default: and case <const-integer-expr>:

Operator int i; is a variable definition, but not initialization. Thus, no variable initialization is bypassed. There is no longer a problem with this definition than in the first place. Of course, the value is assigned when switching to case 1: and not when switching to case 2: but this is no different from what happens in the code outside of switch -statements if people only define variables.

+6
source

The compiler first decides how it will open the switch code for assembly. It may be if or it may be a table like goto . Also, if you write the declaration of the initialization variable together, the compiler tells you that this is error . In other cases, it will be warning (the compiler warns you, but does not resist you). That way you can protect yourself. It just configures the compiler where warnings will be errors . And in order to work with variables in switch correctly, you must specify their scope. For instance:

 switch(i) { case 1: { int j = 0; } break; } 

PS. For C ++, a switch is hell.

From C ++ 11:

C.1.5 Clause 6: statements

6.4.2, 6.6.4 (switch and goto instructions)

Edit: Currently it is not valid to go through an declaration with an explicit or implicit initializer (except for the whole block that has not been entered)

Rationale: Constructors used in initializers can allocate resources that must be removed when exiting the block. Allowing the transition from initializers will require a difficult run-time distribution definition. In addition, any use of an uninitialized object can be a disaster. With this simple C ++ compile-time rule, that if an initialized variable is in scope, then it certainly has been initialized.

Impact on the original function: Removing a semantically well-defined function.

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 type of diagnostics. For example, a project policy may require that all sources be compiled with -Werror, but some files may have exceptions that allow certain types of warnings to be used. Or, a project can selectively enable diagnostics and treat them as errors, depending on which preprocessor macros are defined.

Pss. The compiler knows that your variable is not initialized in a piece of code. Whatever it is static C/C++ analysis (for example, for free cppcheck ) shows your problem place.

+2
source

Enabling warnings (-Wall) in the second case gives:

 foo.cpp:15:8: warning: 'i' may be used uninitialized in this function [-Wuninitialized] 

Slipping after initialization is a mistake, but the compiler does not try to redirect you to uninitialized variables.

+1
source

Source: https://habr.com/ru/post/1441004/


All Articles