zoukankan      html  css  js  c++  java
  • 关于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下结果


  • 相关阅读:
    Moq4在.NET3.5和.NET4版本之间的差异
    TDD中的迭代
    洛谷 3413 萌数
    割点(tarjan)
    hdu-4507 吉哥系列故事——恨7不成妻
    hdu-3709 Balanced Number
    poj-3252 Round Numbers
    hdu 1007 Quoit Design 分治求最近点对
    LA 3905 Meteor 扫描线
    uva 11464
  • 原文地址:https://www.cnblogs.com/win7xt/p/3118687.html
Copyright © 2011-2022 走看看