views:

74

answers:

3

Consider the following code:

int main()
{ 
    int *p;

    ++((int){5});    //compile without err/warning
    &((int){5});     //compile without err/warning

    ++((char *)p);   //Compile-time err: invalid lvalue in increment
    &((char *)p);    //Compile-time err: invalid lvalue in unary '&'

}

Why do the Compound Literals do not generate errors here?

+4  A: 

It is because the "cast" in a compound literal is not a cast at all - it just looks like one.

A compound literal (which is the complete construction (int){5}) creates an lvalue. However a cast operator creates only an rvalue, just like most other operators.

This example would be allowed (but useless, just like your int examples):

++((char *){(char *)p});
&((char *){(char *)p});
caf
+4  A: 

Compound literal doesn't have a cast in it. The (int) part of your compound literals is not a cast. It is just a type part of compound literal syntax. So, the question in this case is whether a compound literal is an object, an lvalue. The answer is yes, a compound literal is an lvalue. For this reason you can apply any operators to it that require an lvalue (like ++ or &).

The second part of your example contains casts. The result of a cast is always an rvalue. You can't use ++ and & with rvalues.

AndreyT
A: 

The "cast" in a compound literal is actually not a cast, rather it is the type of the compound literal.
So, (int){5} is indeed more like an anonymous int, hence a valid lvalue which can be used anywhere an object of the same type (int in this case) could be used.

Whereas, (char *)p is actually a cast (rvalue), so it cannot be incremented ++ or referenced &.

Read Dr.Doobs's in-depth article about compound literals.

N 1.1