Search code examples
cgcc

C Declaration with Self-Assignment Compiles


I was extremely surprised that the following C-code compiles:

int foo() {
    int x = x;
    return x;
}

Is this guaranteed to compile? Is the value of x defined after the assignment (it was zero when I tested in GCC)?


Solution

  • This code has undefined behavior.

    The x on the right of the = serving as an initializer is itself uninitialized at the time it is used. Reading an uninitialized value that has never had its address taken causes undefined behavior as per section 6.3.2.1p2 of the C standard:

    Except when it is the operand of the sizeof operator, the _Alignof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue. If the lvalue has an incomplete type and does not have array type, the behavior is undefined. If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.