【发布时间】:2012-09-22 11:41:44
【问题描述】:
我试图破译导致 C99 和 C11 之间变化的a note。 该说明中提出的更改最终出现在 C11 的 6.2.4:8 中,即:
具有结构或联合类型的非左值表达式,其中 结构或联合包含具有数组类型的成员(包括, 递归地,所有包含的结构和联合的成员)指 到具有自动存储持续时间和临时生命周期的对象。 它的生命周期从计算表达式及其初始值开始 value 是表达式的值。它的生命周期结束时 包含完整表达式或完整声明符的评估结束。 任何尝试修改具有临时生命周期的对象都会导致 未定义的行为。
我了解为什么需要进行更改(可以在here 找到一些讨论。请注意,讨论可以追溯到 C11 之前)。然而,我不明白的是克拉克尼尔森在写他的笔记时所说的旁白:
请注意,这种方法还声明了一个示例,例如 这符合 C99 标准,但不符合标准:
struct X { int a[5]; } f();
int *p = f().a;
printf("%p\n", p);
我明白为什么这个例子不符合 C11 标准。我特别不明白的是它是如何符合 C99 的。而且,如果它是在 C99 下定义的,那么它应该做什么,定义地打印悬空指针的值?
【问题讨论】:
-
我无法理解在 C99 或 C11 下这是不符合标准的,因为它不会尝试修改具有临时生命周期的对象,或者在生命周期结束后访问它。它打印的指针的确切值显然是未知的,但它应该打印一些指针值。
-
@ChrisDodd 在 C11 中未定义的原因是它违反了 6.2.4:2,特别是“当指针指向(或刚刚过去)的对象到达末尾时,指针的值变得不确定它的一生。”。访问不确定的内容在道德上是未定义的行为(它在 J.2 中如此列出:“使用指向生命周期已结束的对象的指针的值 (6.2.4)”,尽管实际的规范主体有点更模糊)。 C99 在这方面非常相似。我看到的唯一区别是 p 不会变得不确定,因为它永远不是确定的。