Standard link for int foo = foo

int foo = foo; compiles. What part of the C ++ standard allows this?

+19
c ++ undefined-behavior
May 31 '11 at 14:28
source share
2 answers

3.3.1 Declaration Point [basic.scope.pdecl]

The declaration point for the name immediately after its full declaration (section 8) and before its initializer (if any),

The behavior is well defined if the declaration is in the file area. If you have a function declaration, and if you use foo later [which will be initialized with some undefined value in this case], it will be undefined.

+26
May 31 '11 at 14:29
source share

It?

 int main() { int foo = foo; } 

The foo object exists after = , according to [basic.scope.pdecl] :

The declaration point for the name immediately after its full declaration (section 8) and before its initializer (if any).

However, the program as a whole is undefined because you are using (on RHS) an uninitialized value:

int x = x; Here [..] x initialized with its own (undefined) value.

and

Although the default value is "output and poorly specified", the lvalue-to-rvalue conversion is performed in the RHS foo expression .

And ( [conv.lval] ):

The value (3.10) of non-function, type without array T can be converted to rvalue. If T is an incomplete type, a program that requires this conversion is poorly formed. If the object to which the lvalue value belongs is not an object of type T and is not an object of a type derived from T, or if the object is not initialized, the program that requires this conversion is undefined.

With appropriate warning levels, they will tell you about it ; however, programs that cause undefined Behavior are allowed to compile. They just can do something when you run them.




Or how about this?

 int foo = foo; int main() {} 

Note that foo is "global." They are initialized to zero as the first step according to [basic.start.init] :

Objects with a static storage duration (3.7.1) must be initialized with zeros (8.5) before any other initialization occurs .

So you get int foo with a value of 0; it is valid at this moment, according to [basic.scope.pdecl] above, and according to [stmt.decl] :

Zero initialization (8.5) of all local objects with static storage duration (3.7.1) is performed until any other initialization takes place. [..]

Then you initialize it with the value foo (itself), i.e. 0.

It's well defined ... if a little cryptic.




In the interest of thoroughness, here is the third and final case:

 int foo = 42; int main() { int foo = foo; } 

Unfortunately, this is the same as in the first case . Since local foo has already been declared and is evaluated in the region at the time of initialization, the initializer uses local foo , and you still adhere to undefined behavior. Global foo not used.

+21
May 31 '11 at 14:29
source share



All Articles