• 常量折叠 const folding


    http://bbs.byr.cn/#!article/CPP/86336?p=1

    下列代码给出输出结果:

    #include"stdafx.h"
    #include <iostream>
    #include "stdlib.h"
     
    using namespace std;
    int main(void)
    {
        const int a = 10;
        int * p = (int *)(&a);
        *p = 20;
        cout << "a = " << a << ", *p = " << *p << endl;
        cout << &a << endl << p << endl;  //本人测试时添加的
        system("pause");
        return 0;
         
    }

    运行结果如下:

    QQ图片20150403133551.png
    --

    可是在vc2013中编译通过,运行正常。而且是多次运行。
    运行结果a=10,a的值没被修改,可是指针P指向的确是a的地址,而对*P赋值20后,a的值居然没变。、
    而且*P的值为20.那么P指向的内存在哪里?
    从运行结果来看:*P和a的地址是一样的,那么为什么从同一地址中取出的值却不一样?
    此题选项为:
    A、编译时出错
    B、编译正常,运行时出错
    C、a=10,*P=10
    D、a=10,*P=20
    E、a=20,*P=10
    F、a=20,*P=20

    几个选项都不对。

    所谓的“undefined behaviour”意思是语言的实现(包括编译器、运行库什么的)做任何事都可以。所以,vc2013能编译通过,而且给出某种“正常”的结果,都是允许的,因为编译器允许做任何事

    之所以会这样,是因为检查错误是有代价的,有时候,为了给出确定的行为,甚至是让程序运行时出错,都会让正确的程序的运行的效率大打折扣。比如,“取a的指针”不是错误,因为就算取了指针,以后也可能只是读而不写;“向*p里赋值”也不是错误,因为指针可以指向只读空间也可以指向读写空间,所以不便于编译时检查。所以,C语言的标准里干脆将其规定为“未定义行为”。它隐含的意思是:既然编译器、运行库做什么事都可以,那么程序员就必须尽一切努力来避免这样的事发生。所以,程序员如果写这样的程序,就是程序员的过失。

    希望阿里的生产环境的应用里没有这样的代码。如果他们依赖于某种“特定的未定义行为”,你就该换个老板了。

    还是注意“语言”和“语言实现”的区别。

    “语言”(C++)规定,const标注的存储空间不可以被赋值,如果赋值就是“未定义行为”;但“语言的实现”(VC、x86处理器、Windows系统)可以在语言的要求内,翻译成任何样子。“把栈内存定义为可读写的”是编译器和系统的选择,而不是C++语言的要求。你可以说,“我的这个程序这次在运行于x86处理器Windows系统上用这个版本VC2013编译,得到的这个可执行文件这个局部变量a分配了栈上的读写空间”,但不能说同样的源代码在别的编译器、系统会有同样的行为。

    总结:常量折叠说的是,在编译阶段,对该变量进行值替换,同时,该常量拥有自己的内存空间,并非像宏定义一样不分配空间,需澄清这点

    http://blog.csdn.net/yby4769250/article/details/7359278

  • 相关阅读:
    第十四周学习进度
    第十三周学习进度
    第十二周学习进度条
    从用户体验角度评价所使用的输入法。
    个人博客十
    数组测试 --Junit
    看了build to win之后的感想
    思考题
    数组中最大子数组之和
    使用Espresso进行UI测试
  • 原文地址:https://www.cnblogs.com/diegodu/p/4428262.html
Copyright © 2020-2023  润新知