C++的常量折叠(三)
背景知识
在开始之前先说一下符号表,这个编译器中的东西。下面看一下百度百科中的描述:
符号表是一种用于语言翻译器中的数据结构。在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如其数据类型、作用域以及内存地址。
符号表在编译程序工作的过程中不断收集、记录和使用源程序中一些语法符号的类型和特征等相关信息。这些信息一般以表格形式存储于系统中。如常数表、变量名表、数组名表、过程名表、标号表等等,统称为符号表。对于符号表组织、构造和管理方法的好坏会直接影响编译系统的运行效率。
还有一个问题:前面说的似乎很让人烦,既然声明成了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++的常量折叠(三)的更多相关文章
- java之常量折叠
为什么会写着篇博客,因为昨天看了关于final关键字的解析.但是有个问题始终没有得到解决,于是请教了我qq上之前添加的知乎大神.他给我回复的第一条消息:常量折叠.身为渣渣猿的我立马查询了这个概念.这是 ...
- C++高级进阶 第四季:const具体解释(二) 常量折叠
一.文章来由 const具体解释之二 二.const 取代 #define const最初动机就是取代 #define. const 优于 #define: (1) #define没有类型检查,con ...
- C++中的常量折叠
先看例子: #include <iostream> using namespace std; int main() { ; int * p = (int *)(&a); *p = ...
- 常量折叠 const folding
http://bbs.byr.cn/#!article/CPP/86336?p=1 下列代码给出输出结果: #include"stdafx.h" #include <iost ...
- const常量折叠
首先来看一个例子: int main(int argc, char* argv[]) { ; int *j = (int *) &i; *j=; cout<<&i<& ...
- C++的常量折叠(二)
前面的C++的常量折叠(一)的最后留下了一个问题,那就是在声明i的时候,加上修饰符volatile关键字,发现结果输出的就不一样了,下面来说一下volatile这个关键字. C/C++中的volati ...
- C++的常量折叠(一)
前言 前几天女票问了我一个阿里的面试题,是有关C++语言的const常量的,其实她一提出来我就知道考察的点了:肯定是const常量的内存不是分配在read-only的存储区的,const常量的内存分配 ...
- const常量,常量折叠,字面常量
const int a=10: 涉及到一个叫常量折叠的概念(认为我这说得太简单或者不好理解的可以google一下它获取更多信息), 即编译器虽然会给a分配空间(如果取a的地址进行操作的时候,会强迫编译 ...
- Python优化机制:常量折叠
英文:https://arpitbhayani.me/blogs/constant-folding-python 作者:arprit 译者:豌豆花下猫("Python猫"公众号作者 ...
随机推荐
- WEKA,一个开源java的数据挖掘工具
开始研究WEKA,一个开源java的数据挖掘工具. HS沉寂这么多天,谁知道偏偏在我申请离职的时候给我安排了个任务,哎,无语. 于是,今天看了一天的Weka. 主要是看了HS提供的三个文章(E文,在g ...
- nodejs中使用递归案例
var http = require('http'); //1.正常逻辑第一步正常请求,动作进行一次的方法: function seqRequest(i,limit){ var req = http. ...
- ORACLE 查找字段在哪些表里存在
查找不是主键的字段在哪些表里存在: select owner, table_namefrom dba_tab_columnswhere lower(column_name)='firstname'; ...
- JavaSE思维导图(四)
- Deep Learning(深度学习)学习笔记整理系列之(二)
Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...
- linux 分割文件
import os import sysimport subprocess if len(sys.argv)<3 : print 'usage: filenum filename' file_n ...
- BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )
建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...
- 保存属性至xml并读取
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...
- 算法学习笔记(LeetCode OJ)
================================== LeetCode的一些算法题,都是自己做的,欢迎提出改进~~ LeetCode:http://oj.leetcode.com == ...
- 【转】杭电ACM试题分类
注:网上搜的 第一篇 1001 这个就不用说了吧1002 简单的大数1003 DP经典问题,最大连续子段和1004 简单题1005 找规律(循环点)1006 感觉有点BT的题,我到现在还没过1007 ...