C标准中使用寿命规则的说明

时间:2019-06-13 07:29:19

标签: c compiler-construction

我正在编写一个C编译器(以llvm作为后端)进行练习,并且规则后跟the C11 standard §6.2.4

在“对象的存储期限”部分中,一种情况使我感到困惑:

  

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

我无法想象这种情况在讨论什么情况,尤其是数组成员part(由于这两个具有临时生存期的非左值,具有数组成员的结构与普通的非左值有什么区别吗?< / strong>)有人可以给我一个代码示例来说明这一点吗?

3 个答案:

答案 0 :(得分:5)

其中没有数组的临时值不必引用具有自动(或实际上任何)存储持续时间的对象。数组之所以特别,是因为数组到指针的转换是一个可以对数组执行的唯一有用的操作,它隐式地要求它具有一个地址,因此编译器必须为其分配内存(并隐式地为整个对象分配内存)。包含它)。非数组左值没有地址。

struct a { int x; };
struct b { int y[2]; };
void foo(int*);
struct a one();
struct b two();

foo(&one().x); // not legal
foo(two().y); // legal, y has an address

答案 1 :(得分:1)

struct Foo {
  int i[1]; //structure contains a member with array type
};

struct Foo getFoo() {
  struct Foo foo;
  foo.i[0] = 1;
  return foo;
}

void test() {
  // getFoo().i life time begin;
  int *p = getFoo().i; //A non-lvalue expression with structure type
  // getFoo().i is automatic storage duration and temporary lifetime
  // getFoo().i life time end;
  assert(*p == 1); // Any attempt to modify an object with temporary lifetime results in undefined behavior.
}

答案 2 :(得分:-1)

SEI CERT C Coding Standard中讨论了该问题(并带有示例)。确实,这是该语言的一种极端情况。

我不在这里复制代码-引用链接就足够了。

这个想法是,在C99中,当函数返回包含数组的结构的那一刻,在包含返回函数的函数的完整表达式结束之前,不得访问/更改该数组。在C11中,直接执行此操作是有效的。

例如,它在C11中有效,但在C99中无效:

++(st().arr)[0]  // try to mutate before the full expression ends.
x=st().arr       // access array from a temporary returned structure
                 // before the sequence point at the end of full expression