博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于C/C++求值顺序
阅读量:6691 次
发布时间:2019-06-25

本文共 1450 字,大约阅读时间需要 4 分钟。

最近碰到一个问题,打印一段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

你可能感兴趣的文章
C++虚函数及虚函数表解析
查看>>
基于sklearn的常用分类任务指标Python实现
查看>>
一些关于Hibernate延迟加载的误区
查看>>
设计模式之缺省适配模式
查看>>
uva 10972 RevolC FaeLoN
查看>>
转 delete 和 delete []的真正区别
查看>>
javaScript引入方式
查看>>
[摘录]验证视图MAC失败 Validation of ViewState MAC Failed
查看>>
asp.net mvc生命周期学习
查看>>
HDU 1212 Big Number 【大数求余模拟】
查看>>
静态类(static)与java值传递、引用传递小测
查看>>
小怪受击身体变红特效代码
查看>>
C语言中函数strcpy ,strncpy ,strlcpy的用法
查看>>
Android深入浅出系列之Bluetooth—蓝牙操作(一)
查看>>
MapReduce入门
查看>>
vs 代码格式化
查看>>
权限管理系统
查看>>
Morris算法-----二叉树遍历
查看>>
linux 关闭selinux 服务
查看>>
JavaOOP-集合框架
查看>>