const关键字

3.1k 词

const 关键字

const 关键字用于定义常量,常量一旦被定义,其值就不能被修改。即变为只读状态,被const修饰的变量编译运行时存放在静态区。

有些编译器或者IDE可能不直接检查指针赋值时const的修饰符,所以可能会出现const修饰的局部变量可用指针修改的情况,但从C98到C23,都把这种操作视为非法的,因此如果你使用了指针去修改const变量,可能会产生因环境问题导致程序无法成功编译的问题。

const修饰变量

测试代码:**[点击运行]**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
const int a=100;
int main(int argc ,char *argv[]){
printf("a=%d\n", a);

a=666;
printf("a=%d\n", a);

int*p=&a;
*p = 888;
printf("a=%d\n", a);

return 0;
}

输出结果:

compilation
1
2
3
4
5
6
7
8
9
10
main.cpp:7:6: error: cannot assign to variable 'a' with const-qualified type 'const int'
a=666;
~^
main.cpp:3:11: note: variable 'a' declared const here
const int a=100;
~~~~~~~~~~^~~~~
main.cpp:10:9: error: cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'
int*p=&a;
^ ~~
2 errors generated.

由以上测试代码可以知道:

1. const修饰的变量不能使用赋值语句修改
2. const修饰的变量不能赋值给非const指针

const修饰指针

const可以修饰变量,这当然包括指针;同时指针也可以指向const修饰的变量,关键字的顺序决定了指针和指针指向的内容是否被修饰符修饰。

静态变量的指针

即指向静态变量的指针,const关键字只修饰了指针指向的内容,而不是指针本身。
静态变量的指针只能指向静态变量,但是指针本身不是静态的,所以可以修改指针的值,但是不可以修改指针指向的变量的值。

写法:
const int* p;//推荐int const *p;//不推荐

测试代码:**[点击运行]**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main (int argc ,char *argv[]){
int const *p;
const int* q;
const int a = 100;
const int b = 200;

p = &a;
q = &b;
printf("p=%d\n", *p);
printf("q=%d\n", *q);

p = &b;
q = &a;
printf("p=%d\n", *p);
printf("q=%d\n", *q);

return 0;
}

输出结果:

output
1
2
3
4
p=100
q=200
p=200
q=100

静态的指针变量

即静态的指针,const关键字只修饰了指针,而不是指针指向的变量。因此可以通过指针修改指针指向的变量的值,但是指针自己不能重新被赋值。

写法:
**int* const p;**可见定义指针的时候星号跟着类型走还是比较规范的。

测试代码:**[点击运行]**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main (int argc ,char *argv[]){
int a = 100;
int b = 200;
int* const p = &a;

printf("p=%d\n", *p);

//尝试修改p指向的内容的值
*p = 666;
printf("p=%d\n", *p);

//尝试修改p的指向 //ERROR block
p = &b;
printf("p=%d\n", *p);//

return 0;
}

输出结果:

output
1
2
3
4
5
6
7
8
9
10
11
12
//不注释掉ERROR代码块的编译报错
main.cpp:16:7: error: cannot assign to variable 'p' with const-qualified type 'int *const'
p = &b;
~ ^
main.cpp:7:16: note: variable 'p' declared const here
int* const p = &a;
~~~~~~~~~~~^~~~~~
1 error generated.

//注释掉ERROR语句的输出:
p=100
p=666

静态变量的静态指针

指针和指针的类型都是静态的,指针本身不能修改,指针指向的内容也不能被修改

写法:
const int* const p;

测试代码: **[点击运行]**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main (int argc ,char *argv[]){
const int a = 100;
const int b = 200;
const int* const p = &a;

printf("p=%d\n", *p);

//尝试修改p指向的内容的值//ERROR block
*p = 666;
printf("p=%d\n", *p);

//尝试修改p的指向 //ERROR block
p = &b;
printf("p=%d\n", *p);//

return 0;
}

输出结果:

output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//不注释掉ERROR代码块的编译报错
main.cpp:11:8: error: read-only variable is not assignable
*p = 666;
~~ ^
main.cpp:15:7: error: cannot assign to variable 'p' with const-qualified type 'const int *const'
p = &b;
~ ^
main.cpp:6:22: note: variable 'p' declared const here
const int* const p = &a;
~~~~~~~~~~~~~~~~~^~~~~~
2 errors generated.

//注释掉ERROR语句的输出:
p=100

总结

const修饰符可以让程序变得更健壮,const经常用在指针变量上,特别是动态申请空间的指针,使用const变量修饰后可以有效防止指针丢失从而造成内存泄漏。但是需要注意的是在定义指针时const修饰符的写法,
const修饰符的位置不同,指针指向的内容和指针本身是否可以被修改的含义也不同。所以应该使用更有规律的定义写法从而提高代码的可读性。