6

6.5.2.5p5

如果复合文字出现在函数体之外,则该对象具有静态存储持续时间;否则,它具有与封闭块关联的自动存储持续时间。

我将这里的“封闭块”解释为“最里面的封闭块”是否正确?(因为如果它不是最里面的,那是什么?) 为什么 gcc 和 clang 表现得好像文字的生命周期是它的封闭函数?

例子:

long foo(long*);

void call_foo()
{
    {foo(&(long){42});}
    {foo(&(long){42});}
    {foo(&(long){42});}
    {foo(&(long){42});}
}

//for comparison

void call_foo2()
{
    {long x=42;foo(&x);}
    {long x=42;foo(&x);}
    {long x=42;foo(&x);}
    {long x=42;foo(&x);}
}

gcc/clang 在 -O3 处生成的代码:

call_foo:
  sub rsp, 40
  mov rdi, rsp
  mov QWORD PTR [rsp], 42
  call foo
  lea rdi, [rsp+8]
  mov QWORD PTR [rsp+8], 42
  call foo
  lea rdi, [rsp+16]
  mov QWORD PTR [rsp+16], 42
  call foo
  lea rdi, [rsp+24]
  mov QWORD PTR [rsp+24], 42
  call foo
  add rsp, 40
  ret
call_foo2:
  sub rsp, 24
  lea rdi, [rsp+8]
  mov QWORD PTR [rsp+8], 42
  call foo
  lea rdi, [rsp+8]
  mov QWORD PTR [rsp+8], 42
  call foo
  lea rdi, [rsp+8]
  mov QWORD PTR [rsp+8], 42
  call foo
  lea rdi, [rsp+8]
  mov QWORD PTR [rsp+8], 42
  call foo
  add rsp, 24
  ret
4

2 回答 2

5

这似乎没有什么好的理由。我只会称它为编译器错误。

于 2017-12-07T12:47:39.947 回答
0

考虑代码:

void whatever(void)
{
    THING *p;
    ...
    if (condition1)
      p=&(THING){...whatever...};
    ...
    doSomethingWith(p);
}

按照标准的编写方式,复合文字只有在分配 top是由if;控制的唯一非复合语句执行时才可用。更改代码,因此if受控的复合语句将需要大量修改:

void whatever(void)
{
    THING *p,temp_thing;
    ...
    if (condition1)
    {
      temp_thing = (THING){...whatever...};
      // Or else temp_thing.field1 = value1; temp_thing.field2=value2; etc.
      p=&temp_thing;
    }
    ...
    doSomethingWith(p);
}

这样的要求将极大地且不必要地破坏复合文字的有用性(因为没有它们也可以编写代码)。一个更合理的规则将表明复合文字的生命周期会延长,直到代码离开使用它的函数,或者重新执行创建它的表达式,以先发生者为准。由于该标准允许编译器以他们认为合适的方式延长自动对象的生命周期,因此编译器这样做的事实不应被视为错误。另一方面,故意比标准要求更有用的质量编译器可能应该明确记录这一事实。否则,未来的维护者可能会声明任何依赖这种合理行为的程序都是“有缺陷的”,

于 2017-12-15T20:58:10.150 回答