[英]Question about GCC Optimizer and why this code always returns 42?
我最近遇到一個錯誤,在switch語句中初始化了一個變量。 我開始玩這個更多,並意識到我不知道GCC在一些優化中試圖做的第一件事。
int main(int argc, char** argv) {
switch (argc) {
case 1000: return 42;
int y = 24;
default: return y;
}
return argc;
}
生成的代碼總是返回42.發生了什么? 為什么int y = 24
muck一切?
$ gcc -Wall -Werror -O2 -c test.c
$ objdump -drwCS -Mintel test.o
testo.o: file format elf64-x86-64
Disassembly of section .text.startup:
0000000000000000 <main>:
0: b8 2a 00 00 00 mov eax,0x2a
5: c3 ret
int main(int argc, char** argv) {
switch (argc) {
case 1000: return 42;
int y = 24;
default: return y;
}
return argc;
}
為了進一步解釋這一點,開關並不完全是線性進展。 與此相當的邏輯是:
“如果argc為1000,則返回42.否則返回y”
int y = 24;
從來沒有使用過,因為它從未到過,編譯器可以優化它,並且由於在默認情況下有UB,它也可以返回42。
要解決這個問題並按照我懷疑你想要的方式行事,你只需要在switch語句之外聲明y
。
int main(int argc, char** argv) {
int y = 24;
switch (argc) {
case 1000: return 42;
default: return y;
}
return argc;
}
switch
中的箱子應視為標簽。 如果我們將您的代碼翻譯為等效的goto-spaghetti,則可能更容易理解:
int main(int argc, char** argv)
{
if(argc == 1000)
goto label_1000;
else
goto label_default;
label_1000: return 42;
int y = 24;
label_default: return y;
return argc;
}
goto label_default
跳過y
的標簽初始化,因此不一定會執行。 你的交換機也會發生同樣的事情。
因此,在switch中聲明變量時的最佳做法是始終在每個案例中使用復合語句:
case 1000:
{
int y = 24;
break;
}
除了防止意大利面條蟲之外,這也將變量的范圍縮小到特定case
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.