在局部作用域(如函数)中,给出以下 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..
}
但我不知道为什么。
C 对表演只字不提。
(C99, 5.1.2.3p1) “本国际标准中的语义描述描述了与优化问题无关的抽象机的行为。”
这取决于实现,但任何好的编译器都可能生成相同的代码。
我这么问是因为我经常读到,最好将所有声明放在最第一行,这样对性能会更好。
我可以向你保证,这纯粹是无稽之谈。发表这样的言论的人根本不知道 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% 的应用程序中这并不重要。
如果没有任何
// code
块接触 x
和 y
,那么您极不可能在这些选项之间遇到明显的性能差异。
如果您想确定使用编译器在硬件架构上发生了什么,您可以随时对代码进行基准测试和/或检查生成的程序集。
1) 会有 -- 在调试中。编译器应该在发布时照顾你。
2)您可能会因为可读性而喜欢它。编译器可以完全“删除”一个常量值。
3)这可以产生影响。局部声明通常是最好的,但这在 C++ 中更为重要,因为实际的构造函数会做一些工作。有时,如果将大对象从循环中拉出,您可能会测量差异(但您的编译器应该为您做到这一点)。
我这么问是因为我经常读到,最好将所有声明放在最第一行,这样对性能会更好。
并非如此。我认为这个想法只是来自过去的语言限制。无论如何,“尽可能本地化”通常是最好的。当然,这可能会因编译器、硬件、实现等的不同而有所不同。
在 C 中,堆栈分配和初始化是微不足道的,您的编译器应该足够好地处理这个问题,以便在大多数情况下性能不是问题。
尝试一些现实世界的基准测试和分析。查看 asm(如 Aix 所说)也有帮助。
如果您没有编写汇编,也没有进行日常分析,并且这完全是 C 语言,那么不值得改变您的编写方式。
我问这个问题是因为我经常读到最好将所有声明放在最第一行,这样对性能会更好。喜欢:
func(){
int x,y,z,w;
long bla,ble;
MYTYPE weeee;
// more declarations..
//code..
}
不,这样做的唯一原因是在早期的 C 中,你必须将所有声明放在函数中的代码之前。
该规则在上世纪末发生了变化。
没有普遍可预测的性能差异。
如果编译器真的很笨,那么第二种形式是最好的。否则,它会优化其他形式。
在C中,我认为这不会有任何区别。 在 C++ 中(不是我知道的问题),根据是否调用构造函数以及是否在循环内声明临时对象,以及调用它们的次数,您会得到很大的差异。
在 C99 中,我不确定后期声明是否在进入函数时分配堆栈空间,或者在进入块时分配堆栈空间。 这会对优化器应该处理的类似(尽管很小)的性能影响产生影响。 根据 Aix 的回答,一个好的方法是查看汇编器,看看幕后发生了什么,