关于C/C++求值顺序

最近碰到一个问题,打印一段buff的数据,大致可以简化为

int i =1;

printf("++i:%d --i:%d\n", ++i, --i);
    结果和期望的不同,gcc下测试结果:++i:1 --i:1;vc6.0下测试结果:++i:1 --i:0然后想起求值顺序的问题,总结一下。
   C语言跟大多数语言一样,没有规定表达式的求值顺序,除了以下几个顺序点:
        ;(分号,标志一条语句结束)
        ,(逗号操作符,函数参数列表里面的逗号只起分隔作用,不是逗号操作符)
        &&和||(逻辑与,逻辑或)
        ? : (条件运算符)
        ()(if,while,for, do..while,以及函数调用)
这些统称为序列点(sequence point),它们的求值顺序有规定。序列点其实就是c/c++对表达式求值顺序唯一的约束,这个约束可以简单理解为:只有一个序列点前后的代码才能确定求值顺序,两个序列点之间的求值顺序是不定的;在两个相邻的序列点之间,一个对象最多只允许它储存的值被修改一次。并且访问这个对象的初始值的唯一目的只能是确定新值。子表达式的任意执行顺序都必须满足这个要求,否则代码的行为将是未定义的。

下面结合几个例子说明
n = n++;                         //两个序列点(分号)之间两次修改n
a[i] = i++;                      //求值顺序是不确定的,《C programming Language 2nd》上的一个例子
n = f1() + f2() + f3();       //f1,f2,f3谁先被调用,谁后被调用,这是不一定的,C语言标准没有对此作规定。

int i = 7;  
printf("%d\n", i++ * i++); //第一个自增操作和第二个自增操作以及乘法操作的顺序是不一定的,所以结果根本无法确定

特别说明一下逗号操作符,函数参数列表里面的逗号只起分隔作用,不是逗号操作符。
逗号操作符一般形式exp1, exp2...。C语言保证exp1在exp2之前求值,并且exp1求值的副作用保证在逗号之前生成。所以象下面这个逗号表达式:
int i = 1;
i++, (i == 2);
最后的值就是1,因为逗号表达式的前半部分i++的副作用(i自增1)在逗号之前已经生成,所以当执行到(i == 2)的时候,i的值已经是2了,所以i == 2成立,(i == 2)的值便作为整个逗号表达式的值。
再比如:printf("%d",--a+b,--b+a);    对于--a + b 和 --b + a 这两个子表达式,求值顺序不确定,并不是早期C语言教程里面从右往左的顺序(下面有例子验证)

针对未定义的求值顺序,不同的编译器的“想法”可能相同可能不同,结果就可能不一样,所以要尽可能避免这种未定义行为。

下面是我在vc6.0和gcc 4.4.7上测试的同一段代码,结果不完全相同。

intmain(intargc,char*argv[])


{


    inti=1;


    inta=1;


    intb=1;




    printf("i ++i %d --i %d\n",++i,--i);


    printf("%d, %d, %d\n",b,(a++,++b),b--);


    printf("%d, %d\n",b--,(a++,++b));




    return 0;


}

VC6.0下结果

gcc 4.4.7下结果


转载于:https://www.cnblogs.com/win7xt/archive/2013/06/05/3118687.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值