关于宏定义的自加与自减分析

前几天在CSDN论坛上看到一篇帖子:


在下面这段简单的代码里,实际的运算结果与笔算的不致;

#include <stdio.h>
#define function(x) ((x)*(x))
int main(void)
{
  int i = 3;
  printf("[01]the result is : %d\n", function(i++));
  printf("[02]the result is : %d\n", function(++i));
}

按照C语言的语法结果应该是: 12, 25


但实际结果是在LINUX的GCC平台编译完后,执行为: 9 , 25


为什么会出现这样的情况了?实际是C标准只对C的自操作做了规定,而对于自运算的组合操作却没有明确规定。那么各个编译器在具体实现时,就有差別了。


为了更清淅的分析清楚这段代码在㡳层是如何运行的,我们看一下这代码汇编,当然,不能看二进制代码了,如果你是神,就另当別论了。
在LINUX下可以用gcc -S sourcode.c來编译出汇编代码。

我们來看最关键的一段

.LCFI2:
        movl    $3, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %esi
        imull   -4(%rbp), %esi
        addl    $1, -4(%rbp)
        addl    $1, -4(%rbp)
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        addl    $1, -4(%rbp)
        addl    $1, -4(%rbp)
        movl    -4(%rbp), %eax
        movl    %eax, %esi
        imull   -4(%rbp), %esi
        movl    $.LC1, %edi
        movl    $0, %eax
        call    printf
        leave
        ret

如果这一段还没有明白的话,那么我们换个角度来看这段汇编代码:
	function(i++)			function(++i)
        movl    $3, -4(%rbp)	    addl    $1, -4(%rbp)
        movl    -4(%rbp), %eax      addl    $1, -4(%rbp)
        movl    %eax, %esi          movl    -4(%rbp), %eax
        imull   -4(%rbp), %esi      movl    %eax, %esi
        addl    $1, -4(%rbp)        imull   -4(%rbp), %esi
        addl    $1, -4(%rbp)        movl    $.LC1, %edi
        movl    $.LC0, %edi         movl    $0, %eax
        movl    $0, %eax            call    printf
        call    printf		

在这里对于汇编不太了解的同学,要做一个超简单的说明,在以上一段代码中,部分汇编的操作符号,含义如下:

imull 是乘法操作

addl 是加法操作


好了,到这里大家有木有发现function(i++), function(++i)之间的別?

对了,在GCC中,前者是先做完乘法做完后, 再加;而对于后者却是先做完加法,再做乘法。这也是我们看到结果和预计的结果有出入。



这个问题,才开始的时候用标准皂C语這,语法规去分析,得出结果与实际运行的结果不一致,致使我花了好长时间,来找原因;但一致没有头绪,前几天在CSDN上看到一大牛提出对于C语言,其中一些不明白的问题,早快捷的办法,就是只接编译成为汇编,去分析汇编语言,因为汇编语言中的语句,是原子操作,对于每一步操作,都可以很清楚的列出来,分析问题来一目了然。当然了,前提是你对汇编有一定的了解。


可能,你觉得,学习C语言,难道还要把汇编语言搞懂,因而就感到害怕了。其实,完全大可不必,如果你不是做㡳层硬件驱动,仅仅是为了分析C语言学习过程中一些不明白惖问题,一些基本的汇编知识就够了。如上面內文中,就两到三个操作符理解意思了,对不代码操行过程,心里就猜个大概。而这个过程对于深入理解C语言很有帮助。


用好奇的心去思考问题,享受其过程中的快乐。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值