Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using an array as a conditional expression valid in C++?

I have this code:

int main()
{
    char buffer[10];
    if( buffer ) {
       return 1;
    }
    return 0;
}

which Visual C++ 10 interprets like this: buffer decays to a pointer, then a pointer is compared against null. When this is compiled with /O2 the check gets eliminated and the code gets equivalent to just return 1;.

Is the code above valid? Does Visual C++ compile it right (I mean the decaying part, not the optimization)?

like image 849
sharptooth Avatar asked Dec 22 '22 04:12

sharptooth


1 Answers

C++11, 6.4/4:

The value of a condition that is an expression is the value of the expression, contextually converted to bool for statements other than switch; if that conversion is ill-formed, the program is ill-formed.

So the standard says that the compiler has to perform any implicit conversions at its disposal to convert the array to a boolean. Decaying the array to pointer and converting the pointer to boolean with a test against against equality to null is one way to do that, so yes the program is well-defined and yes it does produce the correct result -- obviously, since the array is allocated on the stack, the pointer it decays to can never be equal to the null pointer.

Update: As to why this chain of two conversions is followed:

C++11, 4.2/1:

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

So, the only legal conversion from an array type is to a pointer to element type. There is no choice in the first step.

C++11, 4.12/1:

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

There is an implicit conversion directly from bare pointer to boolean; so the compiler picks that as the second step because it allows the desired result (conversion to boolean) to be immediately reached.

like image 142
Jon Avatar answered Dec 23 '22 17:12

Jon