C变量声明的效率

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

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

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

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

谢谢您的帮助。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

并且告诉他不要过早地或微观地优化他的代码的所有人都是错误的。 了解各种代码的成本是多么的不错 。 最优秀的程序员可以很好地掌握各种策略的成本,并在设计时自动将其考虑在内。 你成为程序员的方式就是在初学者时问这类问题。

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

*确定并非如此,但成本仅取决于总空间量,而不是变量数量。

声明根本没有时间。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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