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?
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});
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.
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.
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.