AI智能
改变未来

C/C++中的const


1 C中的const

C中

const

修饰的变量是只读变量,在使用

const

关键字声明定义变量时会给该变量分配内存空间。

const

修饰的全局变量默认是外部链接的,即其它源文件可以直接使用该变量。

const

修饰的局部变量存储在栈区中,不能通过变量名直接修改该变量的值,但是可以通过指针的方式修改该变量对应的值,从某种意义上来说,C中

const

修饰的变量不是真正意义上的常量,可以将其当作一种只读变量。

C中const示例:

// fun.c// c中const修饰的全局变量默认是外部链接的const int num = 100;  // a的本质是只读的变量,存放在文字常量区(内存空间只读)// main.c#include <stdio.h>// 对fun.c中的a进行声明(不要赋值)extern const int num;void test(){printf(\"num = %d\\n\", num);// num = 200;  // error: assignment of read-only variable \'num\'}int main(int argc, char *argv[]){test();return 0;}
#include <stdio.h>void test(){const int data = 200;  // 局部只读变量,通过指针的形式修改data变量的值printf(\"data = %d\\n\", data);  // 200int* p = (int*)&data;*p = 300;printf(\"data = %d\\n\", data);  // 300}int main(int argc, char *argv[]){test();return 0;}

总结:

  • const

    修饰全局变量时,该变量存储在文字常量区(只读),不能通过指针的方式修改其内容

  • const

    修饰局部变量是,该变量存储在栈区中(可读可写),通过指针的方式可以修改其内同

2 C++中的const

C++中

const

修饰的变量不需要创建内存空间,比如定义常量

const int data = 10;

,C++会在一张符号表中添加

name

data

value

为10的一条记录,如下图所示:

既然,

const

修饰的变量没有内存空间,所以在C++中

const

修饰的变量才是真正意义上的常量。

C++中定义声明的全局常量是内部链接的,只能作用于当前的整个文件中,如果想让其它源文件对该常量进行访问的,必须加

extern

关键字将该常量转换成外部链接。

在C++中,是否为

const

常量分配内存空间依赖于如何使用,以下情况会对常量进行内存空间的分配:

  • const

    常量取地址时

  • 使用变量的形式初始化
    const

    修饰的变量时

  • const

    修饰自定义数据类型(结构体、对象)时

C++中const示例:

// fun.c// const修饰的全局变量,默认时内部链接,不能直接被其它源文件使用//const int num = 100;// 可以通过将num转换成外部链接的方式,供其它源文件对num的访问extern const int num = 100;// main.c#include <iostream>using namespace std;extern const int num;struct Person{int num;char name[32];};void test(){cout << \"全局num = \" << num << endl;  // error: undefined reference to `num\'// 1. c++中对const修饰的基础类型的变量不会开辟内存空间,只是将其放到符号表中const int data = 100;// data = 200; // error: 只读cout << \"data = \" << data << endl;// 2. 对data取地址时,系统会给data开辟空间int* p = (int*)&data;*p = 2000;cout << \"*p = \" << *p << endl;  // 2000cout << \"data = \" << data << endl; // 100// 3. 通过变量的形式初始化 const修饰的变量,系统会为其开辟空间int a = 200;const int b = a;  // 系统直接为b开辟空间,不会把b放入到符号表中p = (int*)&b;*p = 3000;30cacout << \"*p = \" << *p << endl;  // 3000cout << \"b = \" << b << endl;  // 3000// 4. const修饰自定义类型的变量,系统会分配空间const Person per = { 100, \"viktor\" };// p1.num = 1000;  // errorcout << \"num = \" << per.num << \", name = \" << per.name << endl;  // 100, viktorPerson* p1 = (Person*)&per;p1->num = 2000;cout << \"num = \" << per.num << \", name = \" << per.name << endl;  // 2000, viktor}int main(int argc, char *argv[]){test();return 0;}

总结:

  • C++中,使用
    const

    定义声明变量时,该变量会先放入到符号表中,不会开辟内存空间;

  • const

    修饰的全局变量默认是内部链接的;

  • const

    修饰的变量进行取地址操作,系统会对该变量开辟空间;

  • 使用其它的变量对
    const

    修饰的变量进行初始化时,系统会对该变量开辟空间;

  • const

    修饰自定义的数据类型,系统为自定义数据开辟空间。

3 C/C++中const异同总结

3.1 const修饰全局变量

全局变量存储在只读的文字常量区,所以C/C++中

const

修饰的全局变量都不可以更改变量对应的内容。

C中

const

修饰的全局变量默认是外部链接的,而C++中默认的是内部链接,如果想使得其变为外部链接可以在

const

修饰的全局变量前加

extern

关键字。

3.2 const修饰局部变量

const

在修饰基础数据类型的局部变量时,在C中会给该变量在栈中开辟内存空间,可以通过指针的方式修改变量的内容;而C++对于

const

修饰基础类型的变量是在符号表中添加一条记录,不会在栈中开辟空间,所以不能通过指针的方式修改变量的值。

C++中对

const

修饰的局部变量是在如何使用的情况下才分配内存,如果对

const

修饰基础数据类型的局部变量进行取地址操作,会对变量分配内存;使用一个变量初始化

const

变量时会分配内存;

const

修饰的自定义数据类型(结构体、对象)会分配内存。

4 const和#define

在旧版本C中,如果想创建一个常量,必须使用预处理器

#define MAX 1024;

。使用宏定义的

MAX

对于编译器来说不知其的存在,因为在程序预处理的过程中,所有的

MAX

已经被替换为1024,于是

MAX

并没有将其加入到符号表中。

如果使用这个常量获得一个编译错误信息时,可能会带来一些困扰,因为这个信息可能会提到1024,但是并没有提到

MAX

此外

MAX

如果被定义在另外一个头文件中,当前可能并不知道1024代表什么,也许解决这个问题要花很长时间。解决办法就是用一个常量替换上面的宏。

const

#define

的区别:

  • const

    有类型,可进行编译器类型安全检查。

    #define

    无类型,不能进行类型检查

示例:

// 宏没有类型,const有#define MAX 1024const short my_max = 1024;void func(short i){cout << \"short函数\" << endl;}void func(int i){cout << \"int函数\" << endl;}void test(){func(MAX);  // int函数func(my_max);  // short函数}
  • const

    有作用域,而

    #define

    不重视作用域,默认定义出到文件结尾。如果定义在指定作用域下有效的常量,那么

    #define

    就不适用

示例:

// 宏的作用域是当前的整个文件,const的作用域以定义的情况决定void my_func(void){// 作用范围是当前复合语句const int my_num = 10;// 作用范围是当前位置到文件结束#define MY_NUM 10}void test(){// cout << \"my_num = \" << my_num << endl;  // err 不识别cout << \"MY_NUM = \" << MY_NUM << endl;  // ok}
  • const

    可以作为命名空间的成员,而如果将宏作为命名空间的成员,失去了命名空间的意义,因为宏作用于当前的文件,而不是只属于某个命名空间的

5 总结

const

由C++采用,并加进标准C中,尽管它们很不一样,在C中,编译器对待

const

如同对待变量一样,只不过带有一个特殊的标记,意识是”你不能改变我“。在C++中定义

const

时,编译器为它创建空间,所以如果两个不同文件定义多个同名的

const

,链接器将发生链接错误。简而言之,

const

在C++中用的更好。

在C++中尽量使用

const

来替换宏定义,避免不必要的麻烦。

另外在C++中可以使用变量定义数组。对于C,在支持C99标准的编译器中,可以使用变量定义数组。

示例:

#include <iostream>using namespace std;void test(){int a = 10;int arr[a];int i = 0;for(; i < 10; i++)arr[i] = i;i = 0;for(; i < 10; i++)cout << arr[i] << \" \";cout << endl;}int main(int argc, char *argv[]){test();return 0;}
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » C/C++中的const