C变量声明的效率

时间:2009-12-24 02:20:24

标签: c optimization variables declaration

在C中声明变量需要多长时间,例如int xunsigned long long var?我想知道它是否会使我的代码在这样的事情上更快。

for (conditions) {
    int var = 0;
    // code
}

这样做会更快,还是更容易?

int var;
for (conditions) {
    var = 0;
    // code
}

感谢您的帮助。

12 个答案:

答案 0 :(得分:14)

一条建议:不要担心哪种语言结构在显微镜下比其他语言结构更快或更慢,而是专注于哪些语言结构让你表达自己最好。

另外,要找出代码花费时间的位置,请使用分析器。

正如其他人所指出的那样,声明纯粹是编译时的事情,它们不会影响执行时间。

答案 1 :(得分:11)

它没有任何区别。在传统实现中,声明本身(不包括初始化)不生成机器指令。函数序言代码通常一次为所有局部变量分配堆栈中的空间,无论它们在何处被声明。

但是,在声明局部变量的情况下,至少在理论上会间接地影响代码的性能。当您将变量声明为尽可能本地(您的第一个变体)时,通常情况下,它会导致函数为其局部变量保留的堆栈帧的较小大小(因为堆栈中的相同位置可以由不同的局部变量共享)在不同的时间)。具有较小的堆栈帧减少了一般的堆栈存储器消耗,即,当执行嵌套的函数调用时,堆栈大小不会快速增长(特别是对于递归函数而言是显着的)。它通常可以提高性能,因为新的堆栈页面分配不常发生,并且堆栈内存位置变得更好。

当然,后面的考虑因素依赖于平台。它可能对您的平台和/或您的应用程序产生很小的影响或没有影响。

答案 2 :(得分:9)

每当你对性能有疑问时,最好的办法就是围绕它进行循环(数百万次迭代)并计时。但是,在这种情况下,您可能会发现没有区别。

正确表达代码意图更为重要。如果您需要在循环外部使用变量,请将其置于外部。如果需要循环内的变量,请在里面声明它。

您应该始终在尽可能最窄的范围内声明和初始化变量。

无论如何,你不应该担心这些类型的微优化(除了最稀有,最稀有的情况)。如果真的需要担心潜在的纳秒性能改进,请衡量差异。您的变量声明不太可能是应用程序中最大的瓶颈。

答案 3 :(得分:5)

根本不需要时间。全局变量的内存在启动时分配,堆栈上的“声明”变量只涉及在调用函数时堆栈指针“向上”移动多远。

答案 4 :(得分:4)

声明纯粹是编译时间,它们在运行时没有任何成本¹。但是第一段代码仍然比第二段好,原因有两个

  • 您应该在声明变量时始终初始化变量,因为它们永远不会有未初始化的值。这与
  • 密切相关
  • 始终使用最窄的变量声明范围

所以你的第一个例子,虽然不比第二个更快,但仍然更好。

所有那些告诉他不要过早或微观优化他的代码的人都错了。知道各种代码的代价是多么昂贵 bad 。最优秀的程序员对各种策略的成本有着坚实的,几乎无关紧要的把握,并在设计时自动考虑到这一点。你成为程序员的方式就是在初学者时提出这类问题。

¹事实上,当每个函数为局部变量分配空间时,成本很低,但无论有多少局部变量*,该成本都是相同的。

*确定这不是真的,但成本仅取决于总空间量,而不是变量数量。

答案 5 :(得分:3)

声明根本没有时间。

编译器会将该行解释为需要在堆栈上存在空间的通知。

答案 6 :(得分:1)

我不在乎这里或那里的纳秒。除非你需要在for循环结束之后访问它的值,否则将变量留在循环中:它将更接近使用它的代码(你的代码将更具可读性),其范围将是由循环本身限制(你的代码会更优雅,更容易出错)。

答案 7 :(得分:1)

正如其他人已经说过的那样,不应该花时间。因此,您需要根据其他因素做出此决定:什么会使您的代码更易读,更不容易出错。通常认为将变量声明为尽可能接近其使用情况是一种好习惯(因此您可以一次性查看声明和用法)。如果它只在内部范围内使用,那么只需在该范围内声明它 - 忘记在这个范围内的性能。

答案 8 :(得分:1)

声明变量确实需要时间,因为它会产生机器语言指令,为堆栈上的变量分配空间。这只是堆栈指针的增量,这需要一个微小但非零的时间。

我相信你的问题是,如果在循环内声明变量,是否需要更多时间(即更多堆栈增量操作)。答案是否定的,因为堆栈仅为循环块递增一次,而不是每次循环执行。所以,无论哪种方式都没有时间差异,即使循环执行数以万亿计的次数。

答案 9 :(得分:1)

免责声明:确切地说,发生的事情取决于您的编译器,架构等。但从概念上讲,这是正在发生的事情:

在方法中声明变量时,它会在堆栈上分配。在堆栈上分配内容只涉及使用变量的大小来增加堆栈指针。因此,例如,如果SP表示堆栈顶部的内存地址,则声明char x会导致SP += 1int x导致SP += 4(开启32位机器。)

当函数退出时,堆栈指针将返回到调用方法之前的位置。因此,解除所有内容的速度也很快。

所以,无论哪种方式,它只是一个添加,无论数据量多少,都需要相同的时间。

智能编译器会将多个变量声明组合到一个add中。

当你在一个循环中声明一个变量时,理论上它可能是通过循环在每次迭代时改变堆栈指针,但同样,智能编译器可能不会这样做。

(一个值得注意的例外是C ++,它做了额外的工作,因为它需要在创建或销毁堆栈分配的对象时调用构造函数和析构函数。)

答案 10 :(得分:1)

我敢打赌,编译的二进制文件在两种情况下都是相同的。

答案 11 :(得分:0)

变量声明由编译器转换为堆栈空间预留。现在,这项工作如何完全取决于平台。在x86和几乎所有流行的架构中,这只是从堆栈帧的地址和\或索引寻址模式中减去从堆栈顶部访问。所有这些都带来了简单的减法\加法的成本,真的无关。

技术上第二个例子效率较低,因为声明发生在循环范围的每个条目中,即每次循环迭代。但是,只有99.99%的可能性,堆栈空间将只保留一次。即使分配操作将被优化掉,尽管技术上应该在每次循环迭代时完成。现在在C ++中,这可能会变得更糟,如果变量有一个构造函数,那么它将在每次循环迭代时运行。

作为一个底线,如果没有适当的分析,你真的不应该担心任何这样的问题。即使这样,在这里有更多有价值的问题要问自己,比如“什么是最易读的方法,更容易理解和维护等等。”