【问题标题】:Lifetime of temporary objects in C11 vs C99C11 与 C99 中临时对象的生命周期
【发布时间】: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 不会变得不确定,因为它永远不是确定的。

标签: c c99 c11


【解决方案1】:

我的理解是,在 C99 中,对象生命周期的最佳粒度是块。因此,虽然 6.5.2.2(以及您提到的注释中提到的其他一些 §)明确表示您无法在下一个序列点之后访问返回值,但从技术上讲,它的地址是 not 不确定的,直到在您离开封闭块之后(不过,您应该为不可访问的对象保留一些存储空间的原因留给读者作为练习)。因此,像

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

在 C99 和 C11 中未定义。在 C11 中,C99 中不存在“临时生命周期”的概念,它允许认为指针在完整表达式结束后立即变为不确定。

【讨论】:

  • “对象生命周期的最佳粒度是块”同意,用于具有自动存储持续时间的对象 (C99 6.2.4:5)
猜你喜欢
  • 2023-02-07
  • 1970-01-01
  • 2013-11-20
  • 2016-12-25
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多