[英]Lifetime of a compound literal
如果復合文字出現在函數主體之外,則對象具有靜態存儲持續時間; 否則,它具有與封閉塊關聯的自動存儲時間。
我是否正確地將“封閉塊”解釋為“最里面的封閉塊”? (因為它不是最內層的,是嗎?) 為什么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.