Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifetime of temporary objects in C11 vs C99

Tags:

c

c99

c11

I am trying to decipher a note that led to a change between C99 and C11. The change proposed in that note ended up in C11's 6.2.4:8, namely:

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. 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 understand why the change was needed (some discussion can be found here. Note that the discussion goes back to before C11). However, what I don't understand is a side remark that Clark Nelson made in writing his note:

Please note that this approach additionally declares an example like this, which was conforming under C99, to be non-conforming:

struct X { int a[5]; } f();
int *p = f().a;
printf("%p\n", p);

I understand why this example is non-conforming under C11. What I specifically fail to understand is how it is conforming under C99. And, if it is defined under C99, what is it supposed to do then, definedly print the value of a dangling pointer?

like image 744
Pascal Cuoq Avatar asked Oct 01 '12 15:10

Pascal Cuoq


1 Answers

My understanding is that in C99, the finest grain of lifetime for an object is the block. Thus, while 6.5.2.2 (and some other § mentioned in the note you refer to) specifically says that you can't access the returned value after the next sequence point, technically its address is not indeterminate until after you have left the enclosing block (the reason why you should have some storage reserved for an inaccessible object is left as an exercise for the reader, though). Thus, something like

struct X { int a[5]; } f();
int *p;
{ p = f().a; }
printf("%p\n", p);

is undefined in C99 as well as in C11. In C11, the notion of "temporary lifetime", that does not exist in C99, allows to consider that the pointer becomes indeterminate as soon as the full expression ends.

like image 123
Virgile Avatar answered Oct 16 '22 06:10

Virgile