那么我们先来讲解这三种指向int类型的指针的写法和含义。
const int*
const int*
表示指向常量整数的指针,也称为指向常量的指针。它的声明方式如下:
const int* p;
它可以指向一个整数常量,但是不能通过指针来修改这个常量的值。例如:
const int num = 10; // 定义一个整数常量
const int* p = # // 让p指向该常量
int a = 20;
p = &a; // 可以让p指向变量a
但是,不能通过指针p修改该常量的值:
*p = 30; // 编译错误,不能修改常量的值
const int* const
const int* const
表示指向常量整数的常量指针,也称为常指针。它的声明方式如下:
const int* const p;
它指向的是一个整数常量,并且指针本身也是一个常量,所以它既不能修改指向的常量的值,也不能让它指向其他的常量。例如:
const int num = 10; // 定义一个整数常量
const int* const p = # // 让p指向该常量,且p本身不能修改
int a = 20;
p = &a; // 编译错误,p本身是一个常量,不能修改
那么该指针的值只能在初始化的时候进行赋值,不能进行修改,但是被指向的值可以修改。
int const*
int const*
与 const int*
是相同的,它也表示指向常量整数的指针,但是它的声明方式的顺序与 const int*
不同,如下所示:
int const* p;
它与 const int*
的区别在于,const
关键字是紧挨着类型名前的,这样更符合C语言的类型规范。在使用上它与 const int*
没有任何区别。
接下来,我们来看两个示例:
示例1
#include <iostream>
int main() {
const int num = 10;
const int* p1 = #
std::cout << *p1 << std::endl; // 输出 10
int a = 20;
p1 = &a;
const int* const p2 = #
std::cout << *p2 << std::endl; // 输出 10
// p2 = &a; // 编译错误,p2是常量指针,不能修改
// *p2 = 20; // 编译错误,p2指向的是常量,不能修改
int const* p3 = #
std::cout << *p3 << std::endl; // 输出 10
p3 = &a;
return 0;
}
输出结果:
10
10
10
在这个示例中,我们定义了一个整数常量 num
,然后用指向常量整数的指针 p1
指向该常量。当我们通过 p1
输出该常量的值时,可以成功输出。然后,我们重新定义了一个整数变量 a
,再让 p1
指向它,同样可以输出 a
的值。接下来定义了一个指向常量整数的常量指针 p2
,并且让它指向 num
常量。当我们输出 p2
指向的常量时,同样可以输出。但是在尝试修改 p2
的值或者修改 p2
指向的 num
常量的值时,我们发现都会编译错误。最后,我们定义了一个与 p1
相同含义的指向常量整数的指针 p3
,同样可以输出 num
常量的值,并且可以让 p3
指向 a
变量。
示例2
#include <iostream>
int main() {
int num = 10;
int* const p1 = #
std::cout << *p1 << std::endl; // 输出 10
*p1 = 20;
std::cout << *p1 << std::endl; // 输出 20
int a = 30;
// p1 = &a; // 编译错误,p1是常量指针,不能修改
const int* p2 = #
// *p2 = 20; // 编译错误,p2指向的是常量,不能修改
return 0;
}
输出结果:
10
20
在这个示例中,我们定义了一个整数变量 num
,并且声明了一个常量指针 p1
,让其指向 num
变量。当我们输出 p1
指向的值时,可以成功输出。然后,我们通过 p1
可以成功修改 num
变量的值。接下来,我们定义了一个整数变量 a
,并尝试让 p1
指向它时,发现编译错误。最后,我们定义了一个指向常量整数的指针 p2
,让它指向 num
变量。我们发现在尝试通过 p2
修改 num
变量的值时,仍然不能成功修改,仍然会编译错误。
综上, const int*
、const int* const
和 int const*
它们之间的区别仍然是比较微妙的。在实际开发中,需要根据具体需求和场景来选择所需的指针类型。