c语言中函数会降低效率吗,在C语言程序中使用临时中间变量,会不会降低效率呢?...

现代C语言编译器如gcc通过“常数传播”和“常数折叠”策略,能有效优化使用临时中间变量的代码,确保效率。即使使用临时变量,编译器也能轻松优化,因此在编写代码时更应注重可读性。编译器在编译阶段就能计算常数表达式,消除无用代码,提高程序效率。
摘要由CSDN通过智能技术生成

在C语言程序开发中,有时为了一行代码不至于过长,或者其他原因,程序员常常会使用一些临时的中间变量,使用临时中间变量的C语言代码,大都可以抽象成类似于下面这样的例子,请看:

int i = 5;

int j = 10;

int result = i+j;

668ddcff15b0af45cfe69fb3785df4b0.png有些小伙伴就有疑问了

到这里,有些小伙伴就有疑问了,使用临时中间变量会降低C语言程序的效率吗?或者说,将上面的 3 行代码写成一行:

int result = 5+10;

是否能够得到更高效率的C语言程序呢?鉴于使用临时中间变量常常能够提升代码的可读性,要是它同时真的会降低程序效率,我们就陷入矛盾了。

究竟有没有必要使用长表达式,代替临时中间变量呢?

其实,绝大多数现代C语言编译器已经足够聪明,优化上述代码轻而易举。我们还是以上述C语言代码为例,对其稍作调整,相关代码如下,请看:

a7096a136fea8ecdbe8a0035b7a2cc23.png

以 gcc 编译器为例,添加 -std=c99 指定 C99 标准,并指定 -O3 优化项,应该能够得到上述C语言代码对应的汇编代码:

movl $15, %esi

C语言编译器常用的一个策略“constant propagation(常数传播,下文讨论)”会将 i+j 在编译阶段计算完毕。

另外值得说明的是,我在上述C语言代码中添加了 printf() 函数读取 result,否则 fun() 函数将直接被优化成下面这样的汇编代码:

func:

rep ret

机器甚至都不会再去计算和保存 i+j,直接就返回了。C语言编译器做出这样的优化,显然可以避免无效代码消耗机器性能,因为 fun() 函数中并无实际的代码要用到 result,再去计算和处理它,显然就是做无用功。

当然了,若是考虑到硬件寄存器,即使没有代码使用到result,对其赋值也可能是有意义的。这是就需要一些其他操作,来避免编译器优化了。这一点,我之前的文章讨论过,感到陌生的读者可以翻翻看看。

7b6476a78ff364686e14b97d11ab086e.png优化它们轻而易举

可见,即使在C语言代码中使用了一些临时的中间变量,也不用太过担心它们会影响效率,因为这对于编译器来说,优化它们轻而易举。

编译器的“常数传播”和“常数折叠”策略

考虑到一些初学者不太熟悉编译器的策略,这里对前文设计的“常数传播”策略稍作解释。常数折叠(Constant folding)以及常数传播(constant propagation)都是C语言编译器对代码做优化使用的策略之一。

“常数折叠”是在编译期间简化常数的过程。常数在C语言程序中仅仅代表一个简单的数值,事实上,若某个变量从未被修改,完全可以将其也当作常数,请看下面这个例子:

i = 320 * 200 * 32;

多数现代C语言编译器不会真的产生两个乘法指令,然后再将结果存储起来,而是辨识是否之后没有代码修改变量 i,若如此,则会在编译阶段就将结果计算出来,之后直接使用计算结果。此即一次典型的“常数折叠”过程,这样做显然可以减小C语言代码尺寸,并且能够得到更高效的程序。

d874d9c49f19840e718c96df33c797a4.png得到更高效的程序

“常数传播”则是一个替代表达式中已知常数的过程,也是在编译时执行的,这里仍然以实例讨论,请看下面这段C语言代码:

int x = 14;

int y = 7 - x / 2;

return y * (28 / x + 2);

编译器执行“常数传播”策略,则 x 会被替换为常数 14,得到下面这样的C语言代码:

int x = 14;

int y = 7 - 14 / 2;

return y * (28 / 14 + 2);

ad45477d8cd76cbccfa2c7d45083cd44.png编译器通常还会执行一些消除无用代码的

继续这一传播过程,则最终得到下面这样的C语言代码:

int x = 14;

int y = 0;

return 0;

编译器通常还会执行一些消除无用代码的过程,以对整个C语言程序优化,因此在现代编译器看来:

int x = 14;

int y = 7 - x / 2;

return y * (28 / x + 2);

其实和简单的 return 0; 没什么两样。

小结

本文在最后介绍了现代C语言编译器常用的“常数折叠”和“常数传播”策略,可见,如今的编译器早已不再是只会逐行“死板”的处理代码了,因此,我们在编写C语言代码时,除非在某些特殊的情况下,否则更多的应该关心代码的可读性。那些复杂的“优化”工作,交给编译器去做就好了。

264a25e766ebabce362d091cff6e16c7.png点个关注吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

未经许可,禁止转载。

举报/反馈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值