c和c++关于const的一些区别
以下参考了网上的一些资料并通过程序验证。
注意,以下情况都是用gcc和g++编译器得到的结果,用vs编译器又会有所不同。
以下说下c和c++中const定义的常量的一些区别:
c++中用const定义了一个常量后,不会分配一个空间给它,而是将其写入符号表(symbol table),这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。但是const定义的常量本质上也是一个变量,是变量就会有地址,那么什么时候会分配内存?看看下面的代码:
int main(){
const int a = ;
int* p = (int*)(&a);
*p = ;
cout<<&a<<endl;
cout<<p<<endl;
cout<<a<<endl;
cout<<*p<<endl;
}
结果:
我们看到,通过 int*p = (int*)(&a);这种方法,可以直接修改const常量对应的内存空间中的值,但是这种修改不会影响到常量本身的值,因为用到a的时候,编译器根本不会去进行内存空间的读取。这就是c++的常量折叠(constant folding),即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。除非需要用到a的存储空间的时候,编译器迫不得已才会分配一个空间给a,但之后a的值仍旧从符号表中读取,不管a的存储空间中的值如何变化,都不会对常量a产生影响。
但是在c中却不是这样.c没有constant folding的概念,用constant定义一个常量的时候,编译器会直接开辟一个内存空间存放该常量。不会进行优化。同样的例子在c下面会产生不同的结果:
int main()
{
const int a = ;
int* p = (int*)(&a);
*p = ;
printf("%x\n",&a);
printf("%x\n",p);
printf("%i\n",a);
printf("%i\n",*p);
return ;
}
结果:
我们看到,在c里面,一个被const定义为常量的值,堂而皇之地被修改了,而且编译器没有报任何错误 !
如果我们进一步深入可以发现,对于以上两个例子来说,a都是定义在某个函数之内的(比如main()函数),不管是c还是c++,本质上都只是将其当成一个普通的局部变量来对待,都只是在栈上分配空间。所以const根本就不能起到阻止修改其内存空间的作用,一个合法的强制类型转换就可以轻松搞定。c++比c好的地方就在于使用了constant folding的机制,使得常量的值跟对应的内存空间无关,从而保护了该常量值。
以上的例子是针对局部的const常量而言,对全局的const变量,c++仍旧采用constant folding策略,故以下代码是行得通的:
//global variable
const int a = ;
int arr[a];
但是c会报错: error: variably modified 'arr' at file scope, 原因在于gcc认为a只是一个普通的全局变量,而变量是不能用来指定数组的长度的。当然,这是针对全局数组而言,如果是局部的数组的话,就算是int a = 3; int arr[a];这种都是可以的,因为c里面还有一种叫变长数组的东西(我晕~,貌似因为两者的实现机制不一样,这个要再看看)
另外,对于a,在c和c++中如果我们仍然用int *p = (int*)(&a);这种方法来修改它内存中的值,编译时不会报错,但是运行时会报段错误,因为a是放在只读的全局数据区中,修改该区中的数据会引发段错误。
在vs编译器下:
1.不支持变长数组,一个变量除非被声明为const,否则不能用来声明数组的长度。
2.const变量,不管是全局的还是局部,都是放在只读数据区,所以无法用前面的方法来修改内存空间里面的值,编译时就会报错。
c和c++关于const的一些区别的更多相关文章
- const int *p与int *const p的区别(转:csdn,suer0101)
本文只是一篇学习笔记,是看了<彻底搞定C指针>中的相关篇幅后的一点总结,仅此而已! 一.先搞清const int *p与int const *p的区别 它们的区别就是:没有区别!! 无论谁 ...
- #define和const的简单区别
面试常问:宏#define和const有什么区别? 1.编译器处理方式 define宏是在预处理阶段展开 const常量是在编译阶段使用 2.类型和安全检查不同 define宏没有类型,不做安全检查, ...
- let、var、const声明的区别
前言 看了方应杭老师的一篇解释let的文章,对JavaScript中的声明有了深刻的理解,这里也就有了总结一下JavaScript中各种声明之间区别的这篇文章. JavaScript中变量声明机制 首 ...
- js中const,var,let区别(转载)
js中const,var,let区别 来源:https://www.cnblogs.com/zzsdream/p/6372729.html 今天第一次遇到const定义的变量,查阅了相关资料整理了这篇 ...
- #define宏常量和const常量的区别
C++ 语言可以用const 来定义常量,也可以用#define 来定义常量.但是前者比后者有更多的优点:(1) const 常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查.而 ...
- const 和 #define区别_fenglovel_新浪博客
const 和 #define区别 (2012-12-11 14:14:07) 转载▼ 标签: 杂谈 (1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使 ...
- void fun() const{}; const void fun(){}; 和void const fun(){}; 的区别?
void fun() const{}; const void fun(){}; 和void const fun(){}; 的区别? const void fun(){};和void const fun ...
- const,var,let区别(转载)
1.const定义的变量不可以修改,而且必须初始化. const b = 2;//正确 // const b;//错误,必须初始化 console.log('函数外const定义b:' + b);// ...
- C++(十九) — const 和 #define 区别
1.const (1)C++对 const 常量的处理过程:当编译器碰到 常量声明 时,在符号表中放入常量,编译时发现使用常量,则直接以符号表中的值替换. (2)如果,编译中发现,对 const 使 ...
- const,var,let 区别
js中const,var,let区别 1.const定义的变量不可以修改,而且必须初始化. 声明的是常量 1 const b = 2;//正确 2 // const b;//错误,必须初始化 3 co ...
随机推荐
- EF Code First Migration总结
开启Migration 1. 通过 Tools->Nuget Package Manager->Package Manager Console 打开Package Manager Cons ...
- netstat常见参数
-a (all)显示所有选项,默认不显示LISTEN相关-t (tcp)仅显示tcp相关选项-u (udp)仅显示udp相关选项-n 拒绝显示别名,能显示数字的全部转化成数字.-l 仅列出有在 Lis ...
- SVG的路径动画效果
使用SVG animateMotion实现的一个动画路径效果,相关代码如下. 在线调试唯一地址:http://www.gbtags.com/gb/debug/c88f4099-5056-4ad7-af ...
- Atitit. 提升开发效率与质量DSL ( 3) ----实现DSL的方式总结
Atitit. 提升开发效率与质量DSL ( 3) ----实现DSL的方式总结 1. 管道抽象 1 2. 层次结构抽象(json,xml etc) 1 3. 异步抽象promise 1 4. Ide ...
- JAVA的安装与软件使用
1.JAVA的安装与环境 2.练习: (1)初识java (2)使用eclipse输出自己的名字
- Html+css 练习写页面发现的错误及解决办法。
最近开始模仿写一些静态页面,今天模仿的是中华咨询网.写了一个简单的js(功能:当鼠标hover一级菜单的时候,设置二级菜单为显示,当鼠标hover二级菜单的选项时候,二级菜单不收回.当鼠标移出菜单一级 ...
- Goodchild教授关于GIS的四大预测的不同看法
Goodchild教授的关于GIS的4个未来发展的预测不断有人在微信朋友圈里转发,虽然现在做的工作GIS只是一个基本的工具之一了,但对这4个预测还是有不少不同看法和一点自己的意见. Goodchild ...
- Serializable 和 Parcelable 区别
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html http://www.cnblogs.com/blu ...
- Entity Framework 5.0基础系列
1.Entity Framework简介 http://www.cnblogs.com/aehyok/p/3315991.html 2.Entity Framework DBFirst尝试http:/ ...
- java.lang.ClassNotFoundException: org.junit.Assume$AssumptionViolatedException
java.lang.ClassNotFoundException: org.junit.Assume$AssumptionViolatedException 在spring框架中进行单元测试,出现标题 ...