How can a variable be used when its definition is bypassed?
In my mind, always, definition means storage allocation.
In the following code, int i
allocates a 4-byte (typically) storage on program stack and bind it to i
, and i = 3
assigns 3 to that storage. But because of goto
, definition is bypassed which means there is no storage allocated for i
.
I heard that local variables are allocated either at the entry of the function ( f()
in this case) where they reside, or at the point of definition.
But either way, how can i
be used while it hasn't been defined yet (no storage at all)? Where does the value three assigned to when executing i = 3
?
void f()
{
goto label;
int i;
label:
i = 3;
cout << i << endl; //prints 3 successfully
}
Long story short; goto
will result is a runtime jump, variable definition/declaration will result in storage allocation, compile time.
The compiler will see and decide on how much storage to allocate for an int
, it will also make so that this allocated storage will be set to 3
when "hitting" i = 3;
.
That memory location will be there even if there is a goto
at the start of your function, before the declaration/definition, just as in your example.
Very silly simile
If I place a log on the ground and my friend runs (with his eyes closed) and jumps over it, the log will still be there - even if he hasn't seen or felt it.
It's realistic to say that he could turn around (at a later time) and set it on fire, if he wanted to. His jump doesn't make the log magically disappear.
Your code is fine. The variable lives wherever it would live had the goto
not been there.
Note that there are situations where you can't jump over a declaration:
C++11 6.7 Declaration statement [stmt.dcl]
3 It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. 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 scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5). [ Example:
void f()
{
// ...
goto lx; // ill-formed: jump into scope of `a'
// ...
ly:
X a = 1;
// ...
lx:
goto ly; // ok, jump implies destructor
// call for `a' followed by construction
// again immediately following label ly
}
—end example ]
Definitions are not executable code. They are just instructions to the compiler, letting it know the size and the type of the variable. In this sense, the definition is not bypassed by the goto
statement.
If you use a class with a constructor instead of an int
, the call of the constructor would be bypassed by the goto
, but the storage would be allocated anyway. The class instance would remain uninitialized, however, so using it before its definition/initialization line gets the control is an error.
上一篇: C#switch语句限制
下一篇: 如何在变量被绕过时使用变量?