我的問題是與C99/GNU-C和C++中的堆棧變量的生命週期有關,當goto通過它們時。這裏有一些相關的問題,但他們都沒有真正回答我的情況。考慮下面的代碼示例:POD堆棧變量的範圍和生命週期通過轉到它時
void Foo(char *ptr)
{
label1:
if (ptr)
{
char string1[50];
strcpy(string1, ptr);
strupr(string1);
printf("upcased string = %s\n", string1);
return;
}
#if CASE_1
char string2[50] = "test";
#else
char string2[50];
strcpy(string2, "test");
#endif
ptr = string2;
goto label1;
}
,我讀了一個跳轉不會引入新的作用域,因此變量應該是可訪問的(理論上)被宣佈之前就。 string2存在於函數範圍,但它不能直接從聲明之前的代碼訪問。另一方面,使用goto和指針變量可以訪問它。 我知道C++需要調用析構函數,當goto跨越對象初始化時,但我沒有發現內置/ POD類型的生命。 使用GCC進行的測試顯示,當編譯器重新使用堆棧空間時,ptr未分配給string2,當分配完成後,它將停止重用它,就好像它「知道」它可以在去。
在C99/C++標準(或者甚至可能僅限於GCC)中是否有任何規則明確表示,這是否允許?我對C++特別感興趣。
編輯:
- 的C的一部分++標準,處理與它
"3.7.3-1 Block-scope variables explicitly declared register or not explicitly declared static or extern have automatic storage duration. The storage for these entities lasts until the block in which they are created exits."
雖然這似乎解釋了上面的代碼,它並沒有真正的,因爲很顯然,編譯器將重用堆棧自動變量的空間作爲優化,當它知道它不會再被使用時。所以需要回答的問題是:是否允許編譯器假定變量在聲明之前不在該位置使用,即使程序流將帶有引用? - 我添加了一個替代案例,它似乎有不同的規則。
- 要回答任何問題,爲什麼我會首先使用這樣一個醜陋的構造:這當然不是我想要編寫普通代碼的方式。它被認爲是兼容的宏的一部分,以允許使用結構化異常以G處理++
我可以擺脫初始化:'char string2 [50]; strcpy(string2,「test」);'因此在這種情況下 – Timo
@Timo:在這種情況下,它是良構的,因爲3.7.3/1(「*這些實體的存儲一直持續到它們被創建的塊退出。*「)和3.8/1(*」T類型對象的生命期在以下情況下結束:如果T是具有非平凡析構函數的類類型(12.4),則析構函數調用開始;或者, 「* –
關於第一個問題:」範圍從轉移點轉移到轉移點「,但考慮到範圍是函數,它不會超出範圍關於第二點:我可以去掉初始化:'char string2 [50]; strcpy(string2,「test」);'所以在這種情況下,第二部分也沒有定義。不適用,對不起,但我不會購買有害goto的教條,事實上它們可以使代碼更具可讀性(如在錯誤處理的情況下),但是對於請問你的問題爲什麼:因爲我可以;) – Timo