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 ...
随机推荐
- Qt 5.3.1 版本应用程序的发布问题
问题描述:用过Qt的朋友,都知道,完成的Qt程序,只能在QT环境里运行.在debug环境里,没有配置环境路线的情况下,必须包含多个dll库,然而每个dll库的大小确实很大的.但有时候还是会失败的,在一 ...
- Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结
Atitit..组件化事件化的编程模型--(2)---------Web datagridview 服务器端控件的实现原理and总结 1. 服务端table控件的几个流程周期 1 1.1. 确认要显示 ...
- Unity中的协程是什么?
什么是协程? 1.协程是一个分部执行,遇到条件(yield return 语句)会挂起,直到条件满足才会被唤醒继续执行后面的代码. 2.Unity在每一帧(Frame)都会去处理对象上的协程.Unit ...
- 从零开始学Bootstrap(2)
继从零开始学Bootstrap(1)后,我们需要实际做一些页面,边学边做.因为前端是一项非常注意实践的技术,知识点太多.太琐碎了,所以我们只能边学边做.根据我们想要做的效果,去查相应的资料.不要想着把 ...
- How Tomcat works — 六、tomcat处理请求
tomcat已经启动完成了,那么是怎么处理请求的呢?怎么到了我们所写的servlet的呢? 目录 Http11ConnectionHandler Http11Processor CoyoteAdapt ...
- WHY翻写NEHE与红龙的3D图形程序 [开源]
个人认为学习3D图形程序开发,有两套经典教程.D3D的<D3D游戏开发编程基础>也就是红龙那本书.OpenGL的NEHE教程.为向经典致敬,将我之前翻写他们的程序开源. 我所做的工作是将其 ...
- 为什么你还在用嵌入式的方式来使用mod_wsgi?
可能你还不知道你的python 网站是否跑在embedded mod of mod_wsgi,不管你知不知道请看下去,因为大部分人都是在这个工作模式下运行的.嵌入式顾名思义就是运行在apache的子 ...
- 【转】Java之WeakReference与SoftReference使用讲解
Java 2 平台引入了 java.lang.ref 包,其中包括的类可以让您引用对象,而不将它们留在内存中.这些类还提供了与垃圾收集器(garbage collector)之间有限的交互. 1.先“ ...
- JAVA的Proxy动态代理在自动化测试中的应用
JAVA的动态代理,在MYBATIS中应用的很广,其核心就是写一个interface,但不写实现类,然后用动态代理来实例化并执行这个interface中的方法,话不多说,来看一个实现的例子: 1.先定 ...
- ASP.NET 4.5 和 Visual Studio 2012 中的新功能
原文地址:http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new#_Toc318097372