簡體   English   中英

復合文字的生命周期

[英]Lifetime of a compound literal

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

似乎沒有任何充分的理由。 我只是稱它為編譯器錯誤。

考慮一下代碼:

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

編寫標准的方式,僅當由if控制的唯一非復合語句執行對p的賦值時,復合文字才可用。 更改代碼,因此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);
}

這樣的要求將實質上不必要地破壞復合文字的用途(因為沒有它們也可以編寫代碼)。 一個更合理的規則將表明,復合文字的生存期將延長,直到代碼離開使用它的功能,或者重新執行創建它的表達式,以先發生的為准。 由於該標准允許編譯器延長自動對象的壽命,無論它們認為合適如何,因此不應將編譯器這樣做的事實視為錯誤。 另一方面,故意要比標准要求有用的高質量編譯器可能應該明確記錄這一事實。 否則,將來的維護者可能會聲明依賴於此類明智行為的任何程序都是“有缺陷的”,並且如果編譯器不再支持它們,則編譯器會更加“高效”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM