简体   繁体   中英

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)?

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 NT” 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.

Yes, the conversion from an array type to bool is well-defined by the standard conversions. Quoting C++11, 4/1 (with the relevant conversions highlighted):

A standard conversion sequence is a sequence of standard conversions in the following order:

— Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion , and function-to-pointer conversion.

— Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions .

— Zero or one qualification conversion.

A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.

Yes.

if( buffer ) means: check if buffer is not NULL . An array variable points to the start of the array (unless you move it) and is equivalent to a pointer.

The optimization just returns 1 because that buffer is allocated on the stack, so it definitely has a value (pointer to the location on the stack), so it's always true.

You said it yourself :

buffer decays to a pointer

Since the array is on the stack, it can not be NULL (unless something goes wrong, like stack smashing).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM