常量是在程序中不能更改的量,在C/C++中有两种方式定义常量,一种是利用define宏定义的方式,一种是C++中新提出来的const型常变量,下面主要讨论它们之间的相关问题;安全
define定义的常量:spa
define是预处理指令的一种,它用来定义宏,宏只是一个简单的替换,将宏变量所对应的值替换,以下面的代码:code
#define NUM 2 int main() { printf("%d", NUM); }
编译器在编译时处理的并非这样的代码,编译器会首先处理预处理指令,根据预处理指令生成相关的代码文件,而后编译这个文件,获得相关的.obj文件,最后经过连接相关的.obj文件获得一个可执行文件,最典型的是咱们通常在.cpp文件中写的#include指令,在处理时首先将所需包含的头文件整个拷贝到这个.cpp文件中,并替换这个#include指令,而后再编译生成的文件,这个中间文件在Windows中后缀为.i,在Visual C++ 6.0中以此点击Project-->Settings-->C/C++,在Project Options最后一行加上'/P'(P为大写)这样在点击编译按钮时不会编译生成obj文件,只会生成.i文件,经过这个.i文件能够看到在作预处理的时候会将 NUM替换成2而后在作编译处理,这个时候点击生成时会出错,由于咱们将编译选项修改后没有生成.obj文件可是在生成时须要这个文件,所以会报错,因此在生成时要去掉这个/P选项。而咱们看到在使用const 定义的时候并无这个替换的操做,与使用正常的变量无异。const型变量只是在语法层面上限定这个变量的值不能够修改,咱们能够经过强制类型转化或者经过内嵌汇编的形式修改这个变量的值,好比下面的代码:blog
int main(int argc, char* argv[]) { const nNum = 10; int *pNum = (int*)&nNum; printf("%d\n", nNum); return 0; }
const nNum = 10; __asm { mov [ebp - 4], 10 } printf("%d\n", nNum); return 0;
可是咱们看到,这两种方式修改后,输出的值仍然是10,这个缘由咱们能够经过查看反汇编代码查看内存
;printf("%d\n", nNum); 00401036 push 0Ah 00401038 push offset string "%d\n" (0042001c) 0040103D call printf (00401070) 00401042 add esp,8
在调用printf的时候,入栈的参数是10,根本没有取nNum值得相关操做,在利用const定义的常量时,编译器认为既然这是一个常量,应该不会修改,为了提高效率,在使用时并不会去对应的内存中寻址,而是直接将它替换为初始化时的值,为了防止这种事情的发生,能够利用C++中的关键字:volatile。这个关键字保证每次在使用变量时都去内存中读取。编译器
咱们能够总结出const和define的几个不一样之处:string
1)define是一个预处理指令,const是一个关键字。io
2)define定义的常量编译器不会进行任何检查,const定义的常量编译器会进行类型检查,相对来讲比define更安全asm
3)define的宏在使用时是替换不占内存,而const则是一个变量,占内存空间编译
4)define定义的宏在代码段中不可寻址,const定义的常量是能够寻址的,在数据段或者栈段中。
5)define定义的宏在编译前的预处理操做时进行替换,而const定义变量是在编译时决定
6)define定义的宏是真实的常量,不会被修改,const定义的其实是一个变量,能够经过相关的手段进行修改。