以下两个代码段之间有什么区别吗?哪一个更好用?其中一个更快吗?
案例1:
int f(int x)
{
int a;
if(x)
a = 42;
else
a = 0;
return a;
}
案例2:
int f(int x)
{
int a;
if(x)
a = 42;
return a;
}
答案 0 :(得分:4)
实际上两个片段都可以返回完全不同的结果,所以没有更好的...
在案例2 中,您可以返回非初始化变量 a ,这可能会导致非零的垃圾值......
如果你的意思是:
int f(int x)
{
int a = 0;
if(x)
a = 42;
return a;
}
然后我会说更好,因为更紧凑(但你只保存一个其他的,没有多少计算浪费)
答案 1 :(得分:3)
问题不是"哪一个更好"。问题是"两者都有效吗?"
答案是不,他们不会同时工作。一个是正确的,另一个是不可能的。因此,性能甚至不是问题。
以下结果导致a
具有"不确定值"或者"未指明的值"在c99标准中提到的3.17.2和3.17.3节(可能是后者,虽然我不清楚。)
int a;
if(x)
a = 42;
return a;
这反过来意味着该函数将返回一个未指定的值。这意味着绝对无法保证您将获得什么价值。
如果你不幸,你可能会得到零,因此继续使用上面这段可怕的代码而不知道你以后会遇到很多麻烦。
如果你幸运,你会立刻得到像0x719Ab32d这样的东西,所以你会立刻知道你搞砸了。
如果你试图编译它,任何体面的C编译器都会给你一个警告,所以你问这个问题意味着你没有启用足够数量的警告。在没有启用最大可能警告数量的情况下,不要尝试编写C代码(或任何代码);它永远不会带来任何好处。了解如何在C编译器上启用警告,并尽可能多地启用它们。
答案 2 :(得分:2)
注意:我假设你的第二个片段中未初始化的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.
如你所见,没有区别。让我们用-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.
现在存在差异,随机参数x的平均第一个版本会更快,因为它的第一个版本比第二个版本少一个。
答案 3 :(得分:0)
如果您的第二个代码是
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;
}
没关系。编译器会将它们转换为相同的优化代码
答案 4 :(得分:0)
我更喜欢这个(你的第二个片段):
int f(int x) {
int a = 0;
if (x) {
a = 42;
}
return a;
}
答案 5 :(得分:0)
在任何一种情况下,你都不需要额外的空间 - 你可以做这样的事情 -
ps -eo user,pid,ppid,comm --sort start_time | head -n "$LINES"
BTW在你的第二个功能中你没有初始化a。