关于const和define的内存分配问题的总结
关于const和define的内存分配问题
const与#define宏定义的区别----C语言深度剖析
1, const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个拷贝。
2, #define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。
3, #define宏没有类型,而const修饰的只读变量具有特定的类型。
总结:const节省了空间,避免了不必要的内存分配,同时提高了效率。编译器通常不为普通的const只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。C++中是不太推荐用宏的,尽量少用.因为C++是强类型的语言,希望通过类型检查来降低程序中的很多错误,而宏只是在编译期前做简单替换,绕过了类型检查,失去了强类型系统的优势支撑。
例如:
#define M 3 //宏常量
const int N=5; // 此时并未将N放入内存中
..............
int i=N; //此时为N分配内存,以后不再分配!
int I=M; //预编译期间进行宏替换,分配内存
int j=N; //没有内存分配
int J=M; //再进行宏替换,又一次分配内存!
原因:const定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以const定义的只读变量在程序运行过程中只有一份拷贝。
在c++我们知道一般是采用const来进行替代#define的。
例如:
const int N=3;//注意采用的是赋值的形式并且末尾有分号
#define N 3
特殊情况
在C中我们知道#define进行预定义的某个数是被分配内存的,其文件在编译预处理过程中就会用定义好的数据去替代文中的符号。
但是const却是不一样的,一般情况下编译器也是不为const创建空间的,只是将这个定义的数字保存在符号表中的。但是在下列几种情况下编译器会为const定义的常量分配内存的。
- 1. 使用了extern头
extern const int N=3;
因为使用了extern我们将可能在外部文件使用N,而const默认的是内部链接,所以我们必须要为之分配内存的。
- 2. 取地址操作
#include<iostream>
using namespace std;
const int M=3;
int main()
{
const int *p=&M;
//当编译器发现有对const定义的常量进行取地址操作时候会对M进行内存分配,
//注意这个地址是const int*类型的,地址中的内容不可以改变的
int *pp=(int*)(&M)
//此处我们将const int*类型强制转化成int * 但是对于*pp的任何赋值操作还是会报错的,
//因为本质上的M是常量不可改变的,这也是const的优点
cout<<*p<<endl;
return 0;
}
- 3. const定义的常量未知的时候,这是#define无法实现的。
#include<iostream>
using namespace std;
int main()
{
const int b=cin.get();//此处const定义的b是未知的所以要为它分配内存,但是一旦分配就不可以改变的。
//但是如果读者此处想在利用未知的const常量来定义数组还是会报错的。
//即int array[b]是不行的,因为编译器在从上往下走的时候是要确定数组的大小的
//但是采用new操作就不会报错的int *array=new int(b);
cout<<b<<endl;
return 0;
}
关于const和define的内存分配问题的总结的更多相关文章
- 面试问题5:const 与 define 宏定义之间的区别
问题描述:const 与 define 宏定义之间的区别 (1) 编译器处理方式不同 define宏是在预处理阶段展开: const常量是编译运行阶段使用: (2) 类型和安全检查不同 ...
- const和#define 区别
1: 编译器处理不同 define宏是在预处理阶段展开,const常量是编译运行阶段使用. 2:类型和安全检查不同 const常量有数据类型,而宏常量没有数据类型,仅仅是展开.编译器可以对前者 ...
- iOS—— static和const联合使用;使用static const 与 #define
static和const联合使用: static将一个全局变量变成局部变量 const将一个局部变量变成局部常量 // 定义了一个局部常量 static const CGFloat ...
- C++编程中const和#define的区别
(1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使用.(2) 类型和安全检查不同 define宏没有类型,不做任何类型检查,仅仅是展开. const常量有具 ...
- const和#define常量的区别
(1) 编译器处理方式不同 define宏是在预处理阶段展开. const常量是编译运行阶段使用. (2) 类型和安全检查不同 define宏没有类型,不做任何类型检查,仅仅是展开. const常量有 ...
- 【编程基础】const与#define的区别
[前言] 相信大家看别人代码的时候都遇到过,有人用#define定义,也有人用const定义. 那么两者的区别到底是什么呢?哪个更好用呢? 网上查了又查,下面总结一下. [总结] 编译器处理方式不同 ...
- 函数定义从零开始学C++之从C到C++(一):const与#define、结构体对齐、函数重载name mangling、new/delete 等
今天一直在学习函数定义之类的问题,下午正好有机会和大家共享一下. 一.bool 类型 逻辑型也称布尔型,其取值为true(逻辑真)和false(逻辑假),存储字节数在不同编译系统中可能有所不同,VC+ ...
- const和#define的区别
在刷题的时候经常遇到定义全局常量我一般都是用#define(可能是因为很少接触const的原因) 在昨天做到51nod1082时照常暴力用#define定义最大.可是提交超时..... 后来看他人写的 ...
- 15分钟弄懂 const 和 #define
什么是const ? 什么是#define? 他们有什么用? 他们有什么区别? 应该怎么用? 总结 1. 什么是const ? const是C/C++中的一个关键字(修饰符), const一般用来定义 ...
随机推荐
- ASP.NET服务器控件使用之Reportviewer 报表
http://blog.csdn.net/oemoon/article/details/7338967 http://www.cnblogs.com/emanlee/archive/2008/09/1 ...
- 托管调试助手“NonComVisibleBaseClass”检测到问题
最近 一次在研究 自动化测试框架White ,程序总是报 “托管调试助手“NonComVisibleBaseClass”在“d:\xxxxxxxxxx.vshost.exe”中检测到问题.” 其他 ...
- iOS-修改Status Bar
一.在info.plist文件中添加一行不但要在 Status bar is initially hidden一行,选择为 YES. 二.在didFinishLaunchingWithOptions方 ...
- Android Http请求
Android HTTP请求封装代码 /** * This class is the Utils of other classes. */ public class HttpUtil { /** 变量 ...
- Android 学习笔记多媒体技术之 Drawable类+Tween(补间动画)+Frame(帧动画)
学习内容: 1.了解Drawable类的作用 2.如何使用Drawable... 3.了解Tween动画... 4.如何创建和使用Tween动画... 1.Drawable类... Drawabl ...
- OpenProcess打开进程返回错误的问题
问题描述 项目中需要做一个小功能:能够查看系统中当前正在运行的进程的内存信息,如内存块类型.分配状态.访问权限等.如下图所示: 需要的信息和上图相差无几.说起来也不算太难,毕竟现成的API已经提供了. ...
- thread_Disruptor
转自 知乎 https://zhuanlan.zhihu.com/p/21355046 order从client端传入,decode后进行matching,一旦存在可成交的价格,就要publish到t ...
- Azure开发者任务之四:在Azure SDK 1.3中挂载调试器的错误
我安装了Windows Azure SDK的1.3版本.我试着创建了一个Azure的“Hello World”应用程序. 我按了“F5”,然后我得到了下面这个错误: 我尝试了“Ctrl+F5”:不使用 ...
- sphinx配置文件sphinx.conf参数详细说明
sphinx配置文件sphinx.conf参数详细说明 sphinx.conf各个参数详细说明 # # Sphinx configuration file sample # # WARNING! Wh ...
- 关于SVN删除后的文件不能重新添加(正常途径不行)
在你自己的机器上(即SVN客户端),把“新建test”文件夹标记为删除,然后提交,在删除之前可以备份“新建test”文件夹,提交后,在当前文件夹下更新SVN.然后把你刚刚备份的文件夹重新放到该目录下. ...