C语言 复合文本的生存期

xuo3flqw  于 2023-03-07  发布在  其他
关注(0)|答案(2)|浏览(114)

6.5.2.5p5表示
如果复合文本出现在函数体之外,则对象具有静态存储持续时间;否则,它具有与封闭块相关联的自动存储持续时间。
我把这里的"封闭块"理解为"最里面的封闭块"对吗?(因为如果它不是最里面的,那是哪个?)Why are gcc and clang behaving as if the lifetime of a literal were its enclosing function?
示例:

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);}
}
  • O3时gcc/clang生成的代码:
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
t9aqgxwy

t9aqgxwy1#

这似乎没有什么好的理由,我只会称之为编译器bug。

jvidinwx

jvidinwx2#

考虑代码:

void whatever(void)
{
    THING *p;
    ...
    p=(someCondition)&(THING){...whatever...} : ...somethingElse...;
    ...
    doSomethingWith(p);
}

按照标准的编写方式,复合字面值只有在对p的赋值在包含它的表达式中执行时才可用,而不需要statement来控制不能单独通过条件运算符控制的内容;更改代码以使用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);
}

这样的要求将大大地和不必要地削弱复合文字的有用性(因为没有它们也可以写代码)。一个更合理的规则是,复合字面值的生存期延长到代码离开使用它的函数,或者创建它的表达式被重新执行,以先发生者为准。由于标准允许编译器以他们认为合适的方式延长自动对象的生存期,编译器这样做的事实不应该被认为是bug。另一方面,一个质量好的编译器,如果有意地想比标准要求的更有用,应该明确地记录这个事实。2否则,将来的维护者可能会宣称任何依赖于这种可感知行为的程序是“有缺陷的”,如果编译器不再支持它们,编译器可能会更“有效”。

相关问题