Consider this code:
void foo()
{
goto bar;
int x = 0;
bar: ;
}
GCC and Clang reject it, because the jump to bar:
bypasses variable initialization. MSVC doesn't complain at all (except using x
after bar:
causes a warning).
We can do a similar thing with a switch
:
void foo()
{
switch (0)
{
int x = 0;
case 0: ;
}
}
Now all three compilers emit errors.
Are those snippets ill-formed? Or do they cause UB?
I used to think that both were ill-formed, but I can't find the revelant parts of the standard. [stmt.goto] doesn't say anything about this, and neither does [stmt.select].
So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended.
Initialization is the process of assigning a value to the Variable. Every programming language has its own method of initializing the variable. If the value is not assigned to the Variable, then the process is only called a Declaration.
Uninitialized means the object has not been given a known value (through any means, including assignment). Therefore, an object that is not initialized but is then assigned a value is no longer uninitialized (because it has been given a known value).
This refers to the process wherein a variable is assigned an initial value before it is used in the program. Without initialization, a variable would have an unknown value, which can lead to unpredictable outputs when used in computations or other operations.
It's ill-formed when the initialization is non-vacuous.
[stmt.dcl]
3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization (including ones in conditions and init-statements). A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has vacuous initialization ([basic.life]). In such a case, the variables with vacuous initialization are constructed in the order of their declaration.
The initializer makes the initialization non-vacuous. To contrast, this
void foo()
{
goto bar;
int x; // no initializer
bar: ;
}
would be well-formed. Though the usual caveats about using x
with an indeterminate value would apply.
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