繁体   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