关于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;
}