引言
当我们在写C语言程序时,通常会用到常量的定义。C语言的常量定义有宏定义、枚举、const
关键字和static
关键字,在这些定义方法中,只有const
和enum
枚举具有类型安全性,也就是编译时会检查有没有用法错误,其中const
是最简便、可维护性最好的,它用于声明常量(不可修改的值)。当const
与指针结合使用时,它可以产生一些有用的效果,使代码更加安全、可靠,并帮助编译器优化。下面笔者详细介绍一下const
与指针结合的常见用法。
常量指针
常量指针是指指向常量数据的指针,这意味着通过该指针不能修改所指向的数据。这对于保护数据的完整性和避免意外修改非常有用。在声明常量指针时,const
关键字放在*
号的左边。例如const int* ptr;
,也可以写成int const * ptr;
,表示声明一个int型指针,该指针指向的值是无法改变的。
例如:
#include <stdio.h>
int main() {
int a = 10;
const int *ptr = &a; //常量指针,指向 int a
//如果我们定义
*ptr = 20;
//那么程序在运行时就会报错,因为 *ptr 被 const 限定了
//但是以下操作是允许的
int b = 20;
ptr = &b;//不能改变 *ptr 但可以改变 ptr
a = 30;//不能通过 *ptr 改变 a 的值,但是可以直接对 a 赋其它值
printf("Value of a: %d\n", a); //输出 a 的值
printf("Value pointed by p: %d\n", *ptr); //输出 ptr 所指向的值
return 0;
}
可见,常量指针主要用于保护所指向的数据,确保通过指针访问数据时不会修改数据的值。它可以让你指向不同的常量数据,但不能修改这些数据。例如,可以将一个常量指针用作函数参数,以传递数据的只读引用。
指针常量
指针常量是指向常量地址的指针,那么它所指向的地址就不能被修改。在声明时,const
关键字放在指针操作符的右边。例如:int* const ptr;
用法如下:
#include <stdio.h>
int main() {
int a = 10;
int *const ptr = &a; //指针常量,指向 int a 的常量指针
//可以通过指针常量修改所指向的数据
*ptr = 20;
//---------
int b = 30;
//但如果进行下面的定义,将是不合法的
ptr = &b;//虽然可以修改指向的数据,但不能修改指向的地址
printf("Value of a: %d\n", a); //输出修改后的 a 的值
printf("Value pointed by p: %d\n", *ptr); //输出 ptr 所指向的值
return 0;
}
因此,指针常量主要用于确保指针本身的稳定性,它指向了特定的内存位置,并且保持不变。通过指针可以修改所指向的数据,但不能修改指针的指向。例如,指向硬件寄存器的指针通常会被声明为指针常量,以确保寄存器地址的不变性。
常量指针常量
我们在指针操作符*
号的左边右边同时加上const
关键字const int* const ptr
就是常量指针常量,是指向常量数据的常量指针,即指针本身的值不可修改,同时所指向的数据也不可修改。
例如:
#include <stdio.h>
int main() {
int a = 10;
const int *const ptr = &a; // 常量指针常量,指向常量 int 的常量指针
//下面两种操作都是非法的
*ptr = 20;
int b = 30;
ptr = &b;
printf("Value of a: %d\n", a); // 输出 a 的值
printf("Value pointed by ptr: %d\n", *ptr); // 输出 ptr 所指向的值
return 0;
}
所以,常量指针常量既不能通过指针修改所指向的数据,也不能修改指针的指向,这样既可以确保指针的稳定性也可以确保数据的稳定性。
总结
这三个名称很多人都分不清,尤其是前两个很容易混淆。其实区分方法很简单,我们知道常量是const
,指针是*
,那么常量指针就是const *
,指针常量就是* const
,常量指针常量就是const * const
。
定义常量指针:const int* ptr;
或 int const* ptr;
定义指针常量:int* const ptr;
定义常量指针常量:const int* const ptr;
或 int const * const ptr;
下面表是对以上三种指针与常量结合的类型的总结。
可以:
指针常量 | 常量指针 | 常量指针常量 |
---|---|---|
可以通过指针访问所指向的数据(只读) | ||
可以让指针指向其他数据 |
不可以:
指针常量 | 常量指针常量 | 常量指针 |
---|---|---|
不能通过指针修改所指向的数据 | ||
不能修改指针的指向 |