In C11 the term temporary lifetime
was defined:
C11 6.2.4p8: A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime. 36) Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression or full declarator ends. Any attempt to modify an object with temporary lifetime results in undefined behavior.
I am wondering why this only applies to rvalues of structure or union type which have a member of type array. What is so special about arrays?
struct x { int xx; };
struct y { int yy[1]; };
(struct x) { 42 }; // *not* a temporary object
(struct y) { { 42 } }; // a temporary object
Why should the first object not be a temporary one while the second is?
Because the return value isn't copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called. These overloaded operator functions return a user-defined type that often isn't copied to another object.
// A temporary object is created to store the return // value. Because the return value isn't copied to another object, a temporary object is created. A more common case where temporaries are created is during the evaluation of an expression where overloaded operator functions must be called.
This concept is known as nameless temporary objects, using this we are going to implement a C++ program for pre-increment operator overloading. In this program, we used nameless temporary object in overloaded member function. Here, we did not create any object inside the member function.
An rvalues is an expression that has no address in memory. A temporary object is an object that created and destroyed in the same expression, so typically objects that are unnamed, or created by the compiler when an implicit conversion is done.
The reason the restriction only applies to temporary objects that contain arrays is because the restriction is only relevant for temporary objects that contain arrays -- when you have an unnamed non-lvalue object that does NOT contain an array, you can't get an address from the object; using &
is explicitly disallowed. However, when the object contains an array, and you access that array by name, you're implicitly getting the address of the first element of the array. Prior to C11, trying to do ANYTHING with that pointer was undefined behavior. With C11, you can now use the object (and the pointer), you just cannot modify it.
Note that the examples you have in the question (with compound literals) are NOT temporary objects -- compound literals are lvalues, so can have their address taken, and have static storage duration.
The main way you get temprary objects is when you have a function that returns a struct (or union) type -- when you call such a function, the returned value is a temprary object. Since it is not an lvalue, you can't use &
on it, but if it contains an array, you can use the array name, and that will implicitly decay to a pointer to the array's first element.
I'm not completely sure about this but here's what I understand from reading
EXP35-C. Do not modify objects with temporary lifetime a few times. This isn't a great language-lawyer
answer, but I'll try to explain it in simpler terms.
Normally a C function cannot return an array. However, you (try to) work around this by sticking an array in a structure, and returning that. Consider this example code:
#include <stdio.h>
struct X { char a[8]; };
struct X salutation(void) {
struct X result = { "Hello" };
return result;
}
struct X addressee(void) {
struct X result = { "world" };
return result;
}
int main(void) {
printf("%s, %s!\n", salutation().a, addressee().a);
return 0;
}
In C99, this program invoked undefined behavior. You're not allowed to even access the array inside of the structure. The reason is that the lifetime of the array ends when the function with the local variable returns.
In C11, they relaxed the rules a bit so you're allowed to access the array, but you're not allowed to modify it.
Because of this subtle difference, that EXP35-C
rule recommends not doing either. Instead, save the array-containing structure result to a local variable:
#include <stdio.h>
struct X { char a[8]; };
struct X salutation(void) {
struct X result = { "Hello" };
return result;
}
struct X addressee(void) {
struct X result = { "world" };
return result;
}
int main(void) {
struct X my_salutation = salutation();
struct X my_addressee = addressee();
printf("%s, %s!\n", my_salutation.a, my_addressee.a);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With