const在C与C++中的区别

  在C中,const不是常量,只能说是一个不能改变的变量(注意是变量),C编译器不能把const当作当作一个编译期间的常量,由于他在内存中有分配,C编译器不知道他在编译期间的值。因此不能做为数组定义时的下标,由于它必须为常量。c++

  在C中,const int a;是能够的,由于这只是声明一个变量,告诉编译器,我这里是声明,指明在别的地方有内存分配。但在C++中这样写是不正确的,C++中const默认是内部连接,C中默认是外部连接,为了起到和c语言同样的效果,C++须要将const修饰为extern,由于extern优先级高于const,因此变量会被变为extern外部连接,起到和C语言同样的效果。[ (1) 内链接:编译器只对正被编译的文件建立存储空间,别的文件可使用相同的表示符或全局变量.C/C++中内链接使用static关键字指定.(2) 外链接:全部被编译过的文件建立一片单独存储空间.一旦空间被建立,链接器必须解决对这片存储空间的引用.全局变量和函数使用外部链接.经过extern关键字声明,能够从其余文件访问相应的变量和函数. ] 通俗的讲:在c++ 中const 对象默认为文件的局部变量。与其余变量不一样,除非特别说明,在全局做用域声明的 const 变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其余文件访问。经过指定 const 变动为 extern,就能够在整个程序中访问 const 对象。数组

  C++中是否为const分配内存空间要看具体状况,若是被声明为extern或者取const变量地址,就须要为const变量分配空间。函数

  当在本身的文件中使用const的时候,C++不会为const常量分配空间,由于这是一种优化措施,没有必要浪费空间去存储一个常量,此时const int a=5 就至关于#define a 5,当在其余文件使用的时,须要分配内存,一样在程序内部引用的时候,也须要分配内存,由于这二者都是采用寻址的技术去使用的,不分配内存就没有地址。C++中定义常量的时候再也不采用define,由于define只作简单的宏替换,并不提供类型检查。优化

  C++中用const定义了一个常量后,不会分配一个空间给它,而是将其写入符号表(symbol table),这使得它成为一个编译期间的常量,没有了存储与读内存的操做,使得它的效率也很高。可是const定义的常量本质上也是一个变量,是变量就会有地址,那么何时会分配内存?spa

 1 int main()
 2 {
 3     const int a = 2;
 4     int* p = (int*)(&a);
 5     *p = 30;
 6     cout << &a << endl;
 7     cout << p << endl;
 8     cout << a << endl;
 9     cout << *p << endl;
10     return 0;
11 }
12  
13 /*运行结果:
14 -----------
15 010FF958
16 010FF958
17 2
18 30
19 -----------
20 */

  经过 int*p = (int*)(&a);这种方法,能够直接修改const常量对应的内存空间中的值,但修改不会影响到常量自己的值,由于用到a的时候,编译器根本不会去进行内存空间的读取。这就是C++的常量折叠constant folding,即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。除非须要用到a的存储空间的时候,编译器无可奈何才会分配一个空间给a,但以后a的值仍旧从符号表中读取,无论a的存储空间中的值如何变化,都不会对常量a产生影响。code

  可是在C语言中却不是这样,C没有constant folding的概念,用const定义一个常量的时候,编译器会直接开辟一个内存空间存放该常量。不会进行优化。一样的例子在C下面会产生不一样的结果:对象

 1 int main()
 2 {
 3     const int a  = 2;
 4     int* p = (int*)(&a);
 5     *p = 30;
 6     printf("%x\n",&a);
 7     printf("%x\n",p);
 8     printf("%i\n",a);
 9     printf("%i\n",*p);
10     return 0;
11 }
12  
13 /*运行结果
14 ------------
15 61fe14
16 61fe14
17 30
18 30
19 ------------*/

  C中,一个被const定义为常量的值,却能被修改,并且编译器不报任何错误 。进一步深刻可发现,对于以上两个例子来讲,a都是定义在某个函数以内的(好比main()函数),不论是C仍是C++,本质上都只是将其当成一个普通的局部变量来对待,都只是在栈上分配空间。因此const根本就不能起到阻止修改其内存空间的做用,一个合法的强制类型转换就能够轻松搞定。C++比C好的地方就在于使用了constant folding的机制,使得常量的值跟对应的内存空间无关,从而保护了该常量值。blog

  以上的例子针对局部的const常量而言,对全局的const变量,C++仍旧采用constant folding策略,故如下代码是行得通的:
1 const int a = 3;
2 int arr[a];

  但C会报错: error: variably modified 'arr' at file scope, 缘由在于GCC认为a只是一个普通的全局变量,而变量是不能用来指定数组的长度的,这是针对全局数组而言。但若是是局部的数组的话,就算是int a = 3; int arr[a];这种都是能够的,若在C和C++中若是咱们仍然用int *p = (int*)(&a);这种方法来修改它内存中的值,编译时不会报错,可是运行时会报错误,由于a是放在只读的全局数据区中,修改该区中的数据会引起段错误。内存

相关文章
相关标签/搜索