背景知识

在开始之前先说一下符号表,这个编译器中的东西。下面看一下百度百科中的描述:

符号表是一种用于语言翻译器中的数据结构。在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址。
符号表在编译程序工作的过程中不断收集、记录和使用源程序中一些语法符号的类型和特征等相关信息。这些信息一般以表格形式存储于系统中。如常数表、变量名表、数组名表、过程名表、标号表等等,统称为符号表。对于符号表组织、构造和管理方法的好坏会直接影响编译系统的运行效率。

还有一个问题:前面说的似乎很让人烦,既然声明成了const,干嘛还老修改啊?

根据C++标准,对于修改const变量,属于:未定义行为(指行为不可预测的计算机代码),这样一来此行为取决于各种编译器的具体实现(即不同编译器可能表现不同)。

看到了吧,C++标准是不提倡这么玩的。

下面看一下前面说的那个对照程序:

int main()
{
int i0 = ; const int i = ; //定义常量i
int *j = (int *) &i; //看到这里能对i进行取值,判断i必然后自己的内存空间
*j = ; //对j指向的内存进行修改
printf("0x%p\n0x%p\n%d\n%d\n",&i,j,i,*j); //观看实验效果 const int ck = ; //这个对照实验是为了观察,对常量ck的引用时,会产生的效果
int ik = ck; int i1 = ; //这个对照实验是为了区别,对常量和变量的引用有什么区别
int i2 = i1; return ;
}

同时把i的声明那条语句改成:

const volatile int i = ;         //定义常量i

我们知道volatile是告诉编译器在翻译源码到汇编语言(机器码)的过程中,不要优化。把源码中对i的访问,翻译成每次都要去内存中抓取数据(这里是在做编译工作,只是把对应的源码翻译成汇编语言),而不是从符号表(常量表)中抓取数据。所以加上volatile关键字的i的访问都是去内存中拿数据,不去常量表中。

现在还有个问题,如果我加上volatile关键字,那么每次对i的访问的语句都被翻译成了”去看内存里的数据“这种行为的汇编语言,不会有常量替换的过程了,那么下面的语句是不是合法了呢?

i = ;

你修改了常量的值,怎么可能合法呢?但是按照上面的说法对于const volatile int类型的i似乎又是合法的。问题出在了这里:

编译器的一部分工作流程是这样的:语法检测->预编译(宏替换,常量替换,*(&i)恒等于i等优化)->编译。所以i = 10这句话在语法检查这个阶段,看到你对一个const常量赋值,就已经报错了,根本到不了编译这个阶段。

但是有的一些编译器似乎无视这个volatile关键字,下面看一下测试的结果:

(1)看vc6.0的结果:

没有volatile关键字的:

有volatile关键字的:

即在VC++6.0编译环境下,在const变量定义时添加volatile修饰符,与不添加效果是一样的。编译器都采取了优化(甚至把编译器优化选项关闭还是如此,无奈了)。

(2)vs2010和g++的测试结果是一样的:

没有volatile关键字:

有volatile关键字:

所以:不建议修改const变量的值,即使修改也要熟悉当前使用的编译器对于该 未定义行为 是如何解释的

C++的常量折叠(三)的更多相关文章

  1. java之常量折叠

    为什么会写着篇博客,因为昨天看了关于final关键字的解析.但是有个问题始终没有得到解决,于是请教了我qq上之前添加的知乎大神.他给我回复的第一条消息:常量折叠.身为渣渣猿的我立马查询了这个概念.这是 ...

  2. C++高级进阶 第四季:const具体解释(二) 常量折叠

    一.文章来由 const具体解释之二 二.const 取代 #define const最初动机就是取代 #define. const 优于 #define: (1) #define没有类型检查,con ...

  3. C++中的常量折叠

    先看例子: #include <iostream> using namespace std; int main() { ; int * p = (int *)(&a); *p = ...

  4. 常量折叠 const folding

    http://bbs.byr.cn/#!article/CPP/86336?p=1 下列代码给出输出结果: #include"stdafx.h" #include <iost ...

  5. const常量折叠

    首先来看一个例子: int main(int argc, char* argv[]) { ; int *j = (int *) &i; *j=; cout<<&i<& ...

  6. C++的常量折叠(二)

    前面的C++的常量折叠(一)的最后留下了一个问题,那就是在声明i的时候,加上修饰符volatile关键字,发现结果输出的就不一样了,下面来说一下volatile这个关键字. C/C++中的volati ...

  7. C++的常量折叠(一)

    前言 前几天女票问了我一个阿里的面试题,是有关C++语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配 ...

  8. const常量,常量折叠,字面常量

    const int a=10: 涉及到一个叫常量折叠的概念(认为我这说得太简单或者不好理解的可以google一下它获取更多信息), 即编译器虽然会给a分配空间(如果取a的地址进行操作的时候,会强迫编译 ...

  9. Python优化机制:常量折叠

    英文:https://arpitbhayani.me/blogs/constant-folding-python 作者:arprit 译者:豌豆花下猫("Python猫"公众号作者 ...

随机推荐

  1. 柯南君:看大数据时代下的IT架构(5)消息队列之RabbitMQ--案例(Work Queues起航)

    二.Work Queues(using the Java Client) 走起   在第上一个教程中我们写程序从一个命名队列发送和接收消息.在这一次我们将创建一个工作队列,将用于分发耗时的任务在多个工 ...

  2. NOI2014 Day2

    NOI2014 Day2 动物园 题目描述:给出一个字符串(长度为\(Len\)),设\(num[i]\)为字符串的前\(i\)个字符构成的子串(\(A\))中,满足\(A\)的前\(L\)个字符既是 ...

  3. HDU 5723 Abandoned country(最小生成树 + 树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5723 [题目大意] n座城市,m条路径,求解: 1.最短的路径和,使得n座城市之间直接或者间接连通 ...

  4. 10.30 NFLS-NOIP模拟赛 解题报告

    总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...

  5. ubuntu15.04下编译 libvirt

    很久没有编译 libvirt了. 工作需要,重新编译. [org_ref]: http://libvirt.org/compiling.html 很简单. 编译过程, 还是很多问题. 依赖包(给懒人参 ...

  6. 布线问题(prime)

    布线问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件:1.把所有 ...

  7. 填充Z形二维数组

    形如  1   3 4 10  2  5 9 11  6  8 12 15  7 13 14 16 的数组称谓Z形二维数组.填充这样的数组其实只要按照Z形进行行走填充即可,设置一个flag指示方向,行 ...

  8. POJ 2342 树形DP入门题

    有一个大学的庆典晚会,想邀请一些在大学任职的人来參加,每一个人有自己的搞笑值,可是如今遇到一个问题就是假设两个人之间有直接的上下级关系,那么他们中仅仅能有一个来參加,求请来一部分人之后,搞笑值的最大是 ...

  9. Javascript 基础编程练习一

    Javascript 基础互动编程,这篇练习结合了function 函数名(), onclick 时间, prompt输入窗口, window.open和confirm窗口, 任务 1.新窗口打开时弹 ...

  10. 8月9日,PS、计算机基础(预科)

    一.   PS         掌握简单的图标修改. 1.图层                 2.保存PSD格式,有图层:JPG格式,没有图层.                 3.魔棒工具(调整值 ...