簡體   English   中英

關於GCC Optimizer的問題以及為什么這段代碼總是返回42?

[英]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.

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