Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
pragma GCC诊断随着二进制文件的变化而变化_C_Gcc_Pragma - Fatal编程技术网

pragma GCC诊断随着二进制文件的变化而变化

pragma GCC诊断随着二进制文件的变化而变化,c,gcc,pragma,C,Gcc,Pragma,我添加了一些GCC警告,并希望显式排除一些表达式,并找到了使用的方法。然而,我意识到,根据我把pragma放在哪里,二进制文件可以改变 例如,考虑下面的片段: #include <stdio.h> int f(int x, int y, int z); int main() { int x, y, z; scanf("%d%d%d", &x, &y, &z); f(x, y, z); return 0;

我添加了一些GCC警告,并希望显式排除一些表达式,并找到了使用的方法。然而,我意识到,根据我把pragma放在哪里,二进制文件可以改变

例如,考虑下面的片段:

#include <stdio.h>

int f(int x, int y, int z);

int main()
{
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    f(x, y, z);
    return 0;
}
  • 生成的代码:

    f:
            push    rbp
            mov     rbp, rsp
            mov     DWORD PTR [rbp-4], edi
            mov     DWORD PTR [rbp-8], esi
            mov     DWORD PTR [rbp-12], edx
            mov     eax, 1
            pop     rbp
            ret
    
    f:
            push    rbp
            mov     rbp, rsp
            mov     DWORD PTR [rbp-4], edi
            mov     DWORD PTR [rbp-8], esi
            mov     DWORD PTR [rbp-12], edx
            cmp     DWORD PTR [rbp-4], 0
            jne     .L2
            cmp     DWORD PTR [rbp-8], 0
            je      .L3
            cmp     DWORD PTR [rbp-12], 0
            je      .L3
    .L2:
            mov     eax, 1
            jmp     .L4
    .L3:
            mov     eax, 0
    .L4:
            pop     rbp
            ret
    
    • f
      的实现:

      int f(int x, int y, int z)
      {
          #pragma GCC diagnostic push
          #pragma GCC diagnostic ignored "-Wparentheses"
          if (x || y && z)
          #pragma GCC diagnostic pop
          {
              return 1;
          }
          return 0;
      }
      
      int f(int x, int y, int z)
      {
          #pragma GCC diagnostic push
          #pragma GCC diagnostic ignored "-Wparentheses"
          if (x || y && z)
          {
          #pragma GCC diagnostic pop
              return 1;
          }
          return 0;
      }
      
    • 生成的代码:

      f:
              push    rbp
              mov     rbp, rsp
              mov     DWORD PTR [rbp-4], edi
              mov     DWORD PTR [rbp-8], esi
              mov     DWORD PTR [rbp-12], edx
              mov     eax, 1
              pop     rbp
              ret
      
      f:
              push    rbp
              mov     rbp, rsp
              mov     DWORD PTR [rbp-4], edi
              mov     DWORD PTR [rbp-8], esi
              mov     DWORD PTR [rbp-12], edx
              cmp     DWORD PTR [rbp-4], 0
              jne     .L2
              cmp     DWORD PTR [rbp-8], 0
              je      .L3
              cmp     DWORD PTR [rbp-12], 0
              je      .L3
      .L2:
              mov     eax, 1
              jmp     .L4
      .L3:
              mov     eax, 0
      .L4:
              pop     rbp
              ret
      

  • 使用
    gcc-std=gnu99-wparenthesses-Werror-O0编译,会产生不同的二进制文件。这是为什么?

    -O0的设计目的不是为了产生高效的二进制文件,或最佳的二进制文件,或不依赖于代码或编译器选项中的细微更改的二进制文件,或诸如此类的东西。查看生成的二进制文件,除了正确性和可能的可调试性之外,期望任何东西都是没有任何意义的。@n.'degents'm。谢谢,但我不明白你的意思,你是说将二进制文件与-O0进行比较没有意义吗?我的目标是理解带有pragma的代码之间的区别,包括开放的花括号和非开放的花括号。是的,这正是我要说的,我的意思是说,没有更多。你可以试着理解其中的区别,但我认为从中没有什么有价值的东西可以学到。在没有优化的情况下,编译器会生成便于生成的代码,并且无论诊断选项如何,期望同样的事情也会很方便是不合理的。@n.“代词m:
    -O0
    不是以特定方式设计的,这并不意味着检查生成的二进制文件没有任何意义。自然界中没有任何东西是被设计出来的,然而我们通过研究物理学、生物学等学科学到了很多东西,并从中获得了很多价值。从表面上看,忽略警告与代码生成无关,因此存在差异的事实表明存在某种联系。这种表面上看不出的联系令人感兴趣。好奇心是有价值的,应该鼓励而不是阻止它。@n.“代词m:可能需要学习的东西可能是关于编译器是如何构造的一些启发。或者可能是
    #pragma
    指令中的一些语义我们不知道。或者编译器中的一些错误或缺点。OP发现了一些奇怪的东西,调查这些奇怪的东西可能会带来有趣的发现。你看了才知道,阻止好奇心是不好的政策。