How can a variable be used when its definition is

2020-02-03 08:58发布

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
}

8条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-02-03 09:35

The control of flow has nothing to do with variable's storage which is reserved at compile time by the compiler.

The goto statement only effects the dynamic initialization of the object. For built-in types and POD types, it doesn't matter, for they can remain uninitialized. However, for non-POD types, this would result in compilation error. For example see this

struct A{ A(){} };  //it is a non-POD type

void f()
{
    goto label;

    A a;     //error - you cannot skip this!

label:
    return;
}

Error:

prog.cpp: In function ‘void f()’:
prog.cpp:8: error: jump to label ‘label’
prog.cpp:5: error:   from here
prog.cpp:6: error:   crosses initialization of ‘A a’

See here : http://ideone.com/p6kau

In this example A is a non-POD type because it has user-defined constructor, which means the object needs to be dynamically initialized, but since the goto statement attempts to skip this, the compiler generates error, as it should.

Please note that objects of only built-in types and POD types can remain uninitialized.

查看更多
对你真心纯属浪费
3楼-- · 2020-02-03 09:35

The definition of a variable DOES NOT allocate memory for the variable. It does tell the compiler to prepare appropriate memory space to store the variable though, but the memory is not allocated when control passed the definition.

What really matters here is initialization.

查看更多
何必那么认真
4楼-- · 2020-02-03 09:36

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.

查看更多
We Are One
5楼-- · 2020-02-03 09:39

In my mind, always, definition means storage allocation.

This is not correct. The storage for the variable is reserved by the compiler when it creates the stack-layout for the function. The goto just bypasses the initialization. Since you assign a value before printing, everything is fine.

查看更多
Melony?
6楼-- · 2020-02-03 09:42

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 ]

查看更多
放荡不羁爱自由
7楼-- · 2020-02-03 09:43

The position of the declaration of i is irrelevant to the compiler. You can prove this to yourself by compiling your code with int i before the goto and then after and comparing the generated assembly:

g++ -S test_with_i_before_goto.cpp -o test1.asm
g++ -S test_with_i_after_goto.cpp -o test2.asm
diff -u test1.asm test2.asm

The only difference in this case is the source file name (.file) reference.

查看更多
登录 后发表回答