Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.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
C++ 在C和C++;编程?_C++_C_Performance_If Statement_Optimization - Fatal编程技术网

C++ 在C和C++;编程?

C++ 在C和C++;编程?,c++,c,performance,if-statement,optimization,C++,C,Performance,If Statement,Optimization,以下两段代码之间有什么区别吗?哪一个更好用?其中一个更快吗 案例1: int f(int x) { int a; if(x) a = 42; else a = 0; return a; } int f(int x) { int a; if(x) a = 42; return a; } 案例2: int f(int x) { int a; if(x)

以下两段代码之间有什么区别吗?哪一个更好用?其中一个更快吗

案例1:

int f(int x) 
{
    int a;
    if(x)
        a = 42;
    else
        a = 0;
    return a; 
}
int f(int x) 
{
    int a;
    if(x)
        a = 42;
    return a; 
}
案例2:

int f(int x) 
{
    int a;
    if(x)
        a = 42;
    else
        a = 0;
    return a; 
}
int f(int x) 
{
    int a;
    if(x)
        a = 42;
    return a; 
}

实际上,这两个代码段可以返回完全不同的结果,所以没有更好的

情况2中,您可以返回一个未初始化的变量a,这可能导致垃圾值不是零

如果你是这个意思:

int f(int x) 
{
    int a = 0;
    if(x)
        a = 42;
    return a; 
}

那么我想说的是更好,因为它更紧凑(但您只节省了一个else,没有多少计算浪费)

实际上,两个代码段都可以返回完全不同的结果,所以没有更好的

情况2中,您可以返回一个未初始化的变量a,这可能导致垃圾值不是零

如果你是这个意思:

int f(int x) 
{
    int a = 0;
    if(x)
        a = 42;
    return a; 
}

那么我想说的是更好,因为它更紧凑(但您只节省了一个else,没有多少计算浪费)

以防您的第二个代码

int f(int x) 
{
    int a=0;
    if(x)
        a = 42;
    return a; 
}
而不是

int f(int x) 
{
    int a;
    if(x)
        a = 42;
    return a; 
}

没关系。如果你的第二个代码是

int f(int x) 
{
    int a=0;
    if(x)
        a = 42;
    return a; 
}
而不是

int f(int x) 
{
    int a;
    if(x)
        a = 42;
    return a; 
}
没关系。编译器会将它们转换为相同的优化代码。

我更喜欢这个(您的第二个代码片段):

  • 任何东西都应该有支架。即使现在if块中只有一行,我也会在以后添加更多
  • 我不把大括号放在它们自己的行上,因为这是毫无意义的浪费空间
  • 为了可读性,我很少将块与条件放在同一行
    • 我更喜欢这个(你的第二个片段):

      • 任何东西都应该有支架。即使现在if块中只有一行,我也会在以后添加更多
      • 我不把大括号放在它们自己的行上,因为这是毫无意义的浪费空间
      • 为了可读性,我很少将块与条件放在同一行
        • 问题不是“哪一个更好”。问题是“两者都有效吗?”

          答案是:不,它们不会同时起作用。一个是正确的,另一个是不可能的。因此,性能甚至不是问题

          以下结果导致
          a
          具有c99标准第3.17.2节和第3.17.3节中提到的“不确定值”或“未指定值”(可能是后者,但我不清楚)

          这又意味着函数将返回一个未指定的值。这意味着,这绝对不能保证你会得到什么价值

          如果你运气不好,你可能会得到零分,因此继续使用上面那段糟糕的代码,而不知道你以后肯定会遇到很多麻烦

          如果你是幸运的,你会马上得到类似0x719Ab32d的东西,所以你会马上知道你搞砸了

          如果您试图编译这个问题,任何一个像样的C编译器都会给您一个警告,因此您提出这个问题的事实意味着您没有启用足够数量的警告。在未启用最大可能警告数的情况下,不要尝试编写C代码(或任何代码);它永远不会带来任何好处。了解如何在C编译器上启用警告,并尽可能多地启用警告。

          问题不是“哪一个更好”。问题是“两者都有效吗?”

          答案是:不,它们不会同时起作用。一个是正确的,另一个是不可能的。因此,性能甚至不是问题

          以下结果导致
          a
          具有c99标准第3.17.2节和第3.17.3节中提到的“不确定值”或“未指定值”(可能是后者,但我不清楚)

          这又意味着函数将返回一个未指定的值。这意味着,这绝对不能保证你会得到什么价值

          如果你运气不好,你可能会得到零分,因此继续使用上面那段糟糕的代码,而不知道你以后肯定会遇到很多麻烦

          如果你是幸运的,你会马上得到类似0x719Ab32d的东西,所以你会马上知道你搞砸了


          如果您试图编译这个问题,任何一个像样的C编译器都会给您一个警告,因此您提出这个问题的事实意味着您没有启用足够数量的警告。在未启用最大可能警告数的情况下,不要尝试编写C代码(或任何代码);它永远不会带来任何好处。了解如何在C编译器上启用警告,并启用尽可能多的警告。

          在这两种情况下,您都不需要额外的空间,您可以这样做-

          int f(int x) 
          {
              if(x)
                  return  42;
              else
                  return  0;
          }
          

          顺便说一句,在第二个函数中,您没有初始化a

          在这两种情况下,您都不需要额外的空间来安装,您可以这样做-

          int f(int x) 
          {
              if(x)
                  return  42;
              else
                  return  0;
          }
          

          顺便说一句,在第二个函数中,您没有初始化a

          注意:我假设第二个代码段中未初始化的a是一个类型,它是int a=0

          我们可以使用gdb检查差异:

          (gdb) list f1
          19  {
          20      int a;
          21      if (x)
          22          a = 42;
          23      else
          24          a = 0;
          25      return a;
          26  }
          (gdb) list f2
          28  int f2(int x)
          29  {
          30      int a = 0;
          31      if (x)
          32          a = 42;
          33      return a;
          34  }
          
          现在让我们看一下带-O3的汇编代码:

          (gdb) disassemble f1
          Dump of assembler code for function f1:
             0x00000000004007a0 <+0>: cmp    $0x1,%edi
             0x00000000004007a3 <+3>: sbb    %eax,%eax
             0x00000000004007a5 <+5>: not    %eax
             0x00000000004007a7 <+7>: and    $0x2a,%eax
             0x00000000004007aa <+10>:    retq   
          End of assembler dump.
          (gdb) disassemble f2
          Dump of assembler code for function f2:
             0x00000000004007b0 <+0>: cmp    $0x1,%edi
             0x00000000004007b3 <+3>: sbb    %eax,%eax
             0x00000000004007b5 <+5>: not    %eax
             0x00000000004007b7 <+7>: and    $0x2a,%eax
             0x00000000004007ba <+10>:    retq   
          End of assembler dump.
          
          (gdb)反汇编f1
          函数f1的汇编程序代码转储:
          0x00000000004007a0:cmp$0x1,%edi
          0x00000000004007a3:sbb%eax,%eax
          0x00000000004007a5:不是%eax
          0x00000000004007a7:和$0x2a,%eax
          0x00000000004007aa:retq
          汇编程序转储结束。
          (gdb)分解f2
          函数f2的汇编程序代码转储:
          0x00000000004007b0:cmp$0x1,%edi
          0x00000000004007b3:sbb%eax,%eax
          0x00000000004007b5:不是%eax
          0x00000000004007b7:和$0x2a,%eax
          0x00000000004007ba:retq
          汇编程序转储结束。
          
          正如你所看到的,没有区别。让我们使用-O0禁用优化:

          (gdb) disassemble f1
          Dump of assembler code for function f1:
             0x00000000004006cd <+0>: push   %rbp
             0x00000000004006ce <+1>: mov    %rsp,%rbp
             0x00000000004006d1 <+4>: mov    %edi,-0x14(%rbp)
             0x00000000004006d4 <+7>: cmpl   $0x0,-0x14(%rbp)
             0x00000000004006d8 <+11>:    je     0x4006e3 <f1+22>
             0x00000000004006da <+13>:    movl   $0x2a,-0x4(%rbp)
             0x00000000004006e1 <+20>:    jmp    0x4006ea <f1+29>
             0x00000000004006e3 <+22>:    movl   $0x0,-0x4(%rbp)
             0x00000000004006ea <+29>:    mov    -0x4(%rbp),%eax
             0x00000000004006ed <+32>:    pop    %rbp
             0x00000000004006ee <+33>:    retq   
          End of assembler dump.
          (gdb) disassemble f2
          Dump of assembler code for function f2:
             0x00000000004006ef <+0>: push   %rbp
             0x00000000004006f0 <+1>: mov    %rsp,%rbp
             0x00000000004006f3 <+4>: mov    %edi,-0x14(%rbp)
             0x00000000004006f6 <+7>: movl   $0x0,-0x4(%rbp)
             0x00000000004006fd <+14>:    cmpl   $0x0,-0x14(%rbp)
             0x0000000000400701 <+18>:    je     0x40070a <f2+27>
             0x0000000000400703 <+20>:    movl   $0x2a,-0x4(%rbp)
             0x000000000040070a <+27>:    mov    -0x4(%rbp),%eax
             0x000000000040070d <+30>:    pop    %rbp
             0x000000000040070e <+31>:    retq   
          End of assembler dump.
          
          (gdb)反汇编f1
          组件转储