在本地范围(如函数)中,给出以下4个示例:
(1)
int x;
int y;
// code...
x = 4;
y = 5;
(2)
int x = 4;
int y = 5;
// code...
(3)
// code...
int x = 4;
// code...
int y = 5;
(4)
// any other possibility
我声明并启动变量的形式有一些性能差异,或编译为我追踪?
修改
我在问,因为我经常阅读,最好将所有声明放在最适合性能的第一行。像:
func(){
int x,y,z,w;
long bla,ble;
MYTYPE weeee;
// more declarations..
//code..
}
但我不知道为什么。
答案 0 :(得分:3)
C对表演一无所知。
(C99,5.1.2.3p1)“本国际标准中的语义描述描述了抽象机器的行为,其中优化问题无关紧要。”
这是依赖于实现的,但任何好的编译器都可能产生相同的代码。
答案 1 :(得分:1)
如果// code
区块都没有触及x
和y
,那么您很可能会在这些选项之间遇到明显的性能差异。
如果您想确定使用编译器在硬件架构上发生了什么,您可以始终对代码进行基准测试和/或检查生成的程序集。
答案 2 :(得分:1)
我问,因为我经常阅读,最好将所有声明放在最适合性能的第一行。
我可以向你保证这纯属无稽之谈。制作此类陈述的人不知道C代码如何被翻译成机器代码。
如果您的3个示例中的任何一个给出了不同的机器代码,我会非常惊讶。
然而存在一种特殊情况:如果变量被声明为“全局”或静态,那么它们将具有静态存储持续时间。然后在调用main()之前初始化它们。所有未由程序员显式初始化的全局/静态都设置为零。所以在这种情况下,你的例子1)会慢一点:
int x; /* global variable, no explicit init so it will get set to
zero before main() is called */
...
x = 4; // variable gets set a second time, elsewhere, in "runtime"
慢于
int x = 4; // global variable, gets initialized before main() is called
然而,这两者之间的性能差异可能只是一条CPU指令,因此99.9%的应用程序无关紧要。
答案 3 :(得分:1)
1)在调试中会有 。编译器应该在发布时照顾你。
2)为了便于阅读,您可能会赞成这一点。编译器可以完全“擦除”一个常量值。
3)这可以有所作为。本地声明通常是最好的,但在C ++中,实际的构造函数可以做一些工作,这一点更为重要。有时,如果从循环中拉出一个大对象,你可能会测量差异(但你的编译器应该为你做这个)。
我问,因为我经常阅读,最好将所有声明放在最适合性能的第一行。
不是这样。我认为这个想法只是来自昔日的语言限制。无论如何,“尽可能在当地”通常是最好的。当然,这可能因编译器,硬件,实现等而异。
在C中,堆栈分配和初始化是微不足道的,并且您的编译器应该很好地处理这个问题,以至于在大多数情况下性能不是问题。
尝试一些真实世界的基准测试和分析。看看asm(正如Aix所说)也可以提供帮助。
如果你没有去编写汇编并且你没有进行每日分析,而且这是严格的C,那么就不值得改变你的写作方式。
答案 4 :(得分:1)
我问,因为我经常阅读,最好将所有声明放在最适合性能的第一行。像:
func(){
int x,y,z,w;
long bla,ble;
MYTYPE weeee;
// more declarations..
//code..
}
不,这样做的唯一原因是在早期的C中你已经将所有声明放在函数中的代码之前。
这条规则在上个世纪末发生了变化。
答案 5 :(得分:0)
没有普遍可预测的性能差异。
答案 6 :(得分:0)
如果编译器真的很笨,那么第二种形式是最好的。否则,它将优化其他形式。
答案 7 :(得分:0)
在C中,我认为它不会有任何区别。在C ++中(不是我所知道的问题),你会根据是否调用构造函数来获得实质性差异,如果临时对象是在循环内声明的,那么它们被调用了多少次。
在C99中,我不确定延迟声明是否在输入函数时或在输入块时分配堆栈空间。这将具有类似的,虽然是次要的,性能影响,优化器应该处理。根据Aix的回答,一个好的方法是看看汇编程序,看看幕后发生了什么,