C 临时变量会减慢我的程序吗?

C 临时变量会减慢我的程序吗?,c,performance,temporary,C,Performance,Temporary,假设我有以下C代码: int i = 5; int j = 10; int result = i + j; 如果我循环了很多次,使用intresult=5+10会更快吗?我经常创建临时变量,以使代码更具可读性,例如,如果这两个变量是从某个数组中获得的,则使用一些长表达式来计算索引。在C语言中这种糟糕的性能明智吗?其他语言呢?现代优化编译器应该优化掉这些变量,例如,如果我们在gcc中使用-std=c99-O3标志()使用以下示例: 对于i+j的计算,这是的形式 注意,我添加了printf,这样我

假设我有以下C代码:

int i = 5;
int j = 10;
int result = i + j;

如果我循环了很多次,使用
intresult=5+10
会更快吗?我经常创建临时变量,以使代码更具可读性,例如,如果这两个变量是从某个数组中获得的,则使用一些长表达式来计算索引。在C语言中这种糟糕的性能明智吗?其他语言呢?

现代优化编译器应该优化掉这些变量,例如,如果我们在
gcc
中使用
-std=c99-O3
标志()使用以下示例:

对于
i+j
的计算,这是的形式

注意,我添加了
printf
,这样我们就有了副作用,否则
func
将被优化为:

func:
  rep ret
这些优化在“仿佛”规则下是允许的,该规则只要求编译器模拟程序的可观察行为。C99标准草案第5.1.2.3节《程序执行》对此进行了说明,其中规定:

在抽象机器中,所有表达式都按照 语义。实际的实现不需要评估 表达式,如果它可以推断其值未使用且 产生所需的副作用(包括调用 函数或访问易失性对象)


另请参见:

虽然代码中的各种细微差异都会以略微改善或恶化性能的方式干扰编译器的行为,但原则上,只要程序的含义没有改变,使用这样的临时变量不会对性能产生任何影响。一个好的编译器应该以任何一种方式生成相同或类似的代码,除非您有意在关闭优化的情况下构建代码,以便获得尽可能接近源代码的机器代码(例如,出于调试目的)。

对于优化编译器来说,这是一项很容易优化的任务。它将删除所有变量,并用
15
替换
result


常量折叠几乎是最基本的优化。

您给出的示例对于编译器来说很容易优化。使用局部变量缓存从全局结构和数组中提取的值实际上可以加快代码的执行。例如,如果您从for循环中的复杂结构中提取某些内容,而编译器无法对其进行优化,并且您知道该值没有改变,则局部变量可以节省大量时间。

您可以使用GCC(也可以使用其他编译器)生成中间汇编代码,并查看编译器的实际操作。

这里讨论了如何打开程序集列表:


检查生成的代码并查看编译器实际执行的操作可能很有帮助。

您遇到的问题与我在尝试了解编译器执行的操作时遇到的问题相同--您制作一个简单的程序来演示该问题,并检查编译器的汇编输出,只是意识到编译器已经优化了你想让它做的一切。您可能会发现main()中的一个相当复杂的操作本质上简化为:

push "%i"
push 42
call printf 
ret
您最初的问题不是“int i=5;int j=10……会发生什么情况?”而是“临时变量通常会导致运行时惩罚吗?”

答案可能不是。但是,您必须查看特定、非平凡代码的程序集输出。如果CPU有很多寄存器,比如ARM,那么i和j很可能在寄存器中,就像这些寄存器直接存储函数的返回值一样。例如:

int i = func1();
int j = func2();
int result = i + j;
几乎可以肯定的是,机器代码与:

int result = func1() + func2();

我建议您使用临时变量,如果它们使代码更易于理解和维护,并且如果您真的试图收紧循环,您将查看程序集输出,以找出如何尽可能提高性能。但若并没有必要,也不要在几纳秒内牺牲可读性和可维护性。

优化编译器将使代码变得有效:
int result=15编译器将优化您的代码。更有效的方法是专注于循环中重复的(部分)计算,这在循环开始之前会更好。我认为他指的是任何临时变量,即:使用a=b+c;d=a+e;比使用a=b+c+d+e慢;如果以编译器无法优化的方式进行,则可能会占用更多内存,但速度不应较慢。最好的关注点或工作效率,除非它是商业和关键性能代码。@WeatherVane,尽管大多数编译器至少在某种程度上也会这样做。总的来说,我认为最好关注代码的可维护性,而不是像这样的微优化。@PeteBecker,我恐怕这不是一个有成效的建议。尝试这样的事情并得到错误的印象是很容易的,因为你碰巧选择了(或没有选择)一个例外情况。如果不清楚编译器是如何工作的,那么仅仅测试几个用例不应该以任何方式让您相信它适用于所有情况;做出这样的概括可能非常危险,并且经常会导致错误。我如何才能看到我的C代码将生成什么程序集?@REACHUS,在
gcc
use
gcc-S-o asm_output.S app.C
下,我认为这并不能解决问题。给出的例子很简单,但我认为“如果两个变量是从某个数组中获得的,使用一些长表达式来计算指数”这一部分在这里更为重要,而且这不能被优化掉,或者可以吗?@ArturoTorresSánchez变量只是一个人类概念。没有真正的变量。编译器看到的是对表达式的引用,然后是assemb
int i = func1();
int j = func2();
int result = i + j;
int result = func1() + func2();