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下结果


  • 相关阅读:
    tensorflow2.0 GPU和CPU 时间对比
    第一次使用FileZilla Server
    PremiumSoft Navicat 15 for Oracle中文破解版安装教程
    Unmapped Spring configuration files found. Please configure Spring facet or use 'Create Default Context' to add one including all unmapped files.
    ng : 无法加载文件 D: odejs ode_global g.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。
    angular
    Github上优秀的go项目
    win10---file explore 中remove quick access folder
    react--useEffect使用
    linux---cat 和 grep 的妙用
  • 原文地址:https://www.cnblogs.com/win7xt/p/3118687.html
Copyright © 2011-2022 走看看