19

我试图破译导致 C99 和 C11 之间变化的注释。该说明中提出的更改最终出现在 C11 的 6.2.4:8 中,即:

具有结构或联合类型的非左值表达式,其中结构或联合包含具有数组类型的成员(递归地,包括所有包含的结构和联合的成员)是指具有自动存储持续时间和临时生命周期的对象。它的生命周期从计算表达式时开始,它的初始值是表达式的值。当包含完整表达式或完整声明符的评估结束时,它的生命周期结束。任何修改具有临时生命周期的对象的尝试都会导致未定义的行为。

我理解为什么需要进行更改(可以在此处找到一些讨论。请注意,讨论可以追溯到 C11 之前)。然而,我不明白的是克拉克尼尔森在写他的笔记时所说的旁白:

请注意,这种方法另外声明了一个符合 C99 标准的示例为不符合标准:

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

我明白为什么这个例子在 C11 下不符合标准。我特别不明白的是它是如何符合 C99 的。而且,如果它是在 C99 下定义的,那么它应该做什么,定义地打印悬空指针的值?

4

1 回答 1

8

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.

于 2012-10-02T08:23:17.960 回答