一、指针定义
指针 本质上是一个变量,但它存储的不是普通数据(比如整数、字符),而是另一个变量在内存中的地址。
cs
char val1 = 'a';
char* p = &val1;//val1是什么类型,*p就是什么类型
二、解引用
解引用是针对指针变量 的操作,通过 * 运算符(解引用运算符),访问指针变量中存储的地址所指向的内存空间里的数据。
cs
int num = 0;
int *p3 = #
*p3 = 5;
注:禁止对NULL进行解引用操作 指针操作会崩溃
int*p;//p变量随机值 p的值可能是内存中任意位置的地址(是未知数)
对一个未知地址(野指针/悬挂指针)进行解引用,指针崩溃
三、const
cs
const int val =0;//定义一个指针 指向val
cs
const int *p=&val;//需要对*p行为加上常性限制
*p对元素访问正确
*p=1;错误
cs
const int **q=&p;//由于p类型是const int *所以q类型是const int **
通过q不能对其**q的值进行修改
cs
const int *p=&val;//const修饰*p,说明*p具有常性 *p=1是错误的,p指向之物的值不允许被修改
int*const p=&val;const修饰p说明p具有常性 p=&a是错误的,p的指向不允许被修改
const int*p const p=&val;const修饰p也修饰*p 说明p和*p都具有常性,既不能修改其指针指向,又不可以改变其所指向之物的值
-
const int *p→p指向const int→ 指向的 int 是只读(内容不能改)。 -
int *const p→const p是int *→ 指针 p 本身是只读(地址不能改)。 -
const int *const p→ 指针 p 本身只读,且指向的 int 也只读。
四、权限大小
- 无
const的指针(int *p):权限最大(能改地址、能改内容)。 - 限制内容的指针(
const int *p):权限中等(能改地址、不能改内容)。 - 限制地址的指针(
int *const p):权限中等(不能改地址、能改内容)。 - 双限制指针(
const int *const p):权限最小(地址和内容都不能改)
1、将权限大赋值给权限小的类型
cs
#include <stdio.h>
int main() {
int a = 10, b = 20;
int *p1 = &a; // 权限大:地址、内容都能改
// 权限小:const限制地址,地址不能改、内容能改
int *const p2 = p1; // 合法!权限大 → 权限小(加"地址只读"限制)
// 验证p2的权限
*p2 = 30; // 合法!内容能改
// p2 = &b; // 错误!地址不能改
printf("a = %d\n", a); // 输出:30
return 0;
}
2.权限可以缩小不允许放大,权限和级别对等情况下考虑缩小问题
cs
#include <stdio.h>
int main() {
int a = 10;
int *p1 = &a; // 1级:无限制,权限最大
// 1→2:给内容加限制(const int *p)
const int *p2 = p1; // 合法!权限缩小(内容从可改→只读)
// *p2 = 20; // 被限制,无法修改内容
// 1→2:给地址加限制(int *const p)
int *const p3 = p1; // 合法!权限缩小(地址从可改→只读)
// p3 = &a; // 被限制,无法修改地址
return 0;
}
cs
#include <stdio.h>
int main() {
int a = 10;
const int *p1 = &a; // 2级:内容只读、地址可改
int *p2;
// 2→1:试图解除内容的const限制(权限放大)
// p2 = p1; // 编译器直接报错:discards 'const' qualifier
// 即使强制转换,也属于危险操作(不推荐)
p2 = (int *)p1;
*p2 = 20; // 看似能改,但违反const规则,可能导致未定义行为
return 0;
}
例题:

第一种情况:
int* p = &val//权限对等(无 const→无 const),直接取 val 地址赋值,可通过*p修改 val,也可修改p的地址。
const int* p = &val;//权限缩小 (无 const→限制内容),p指向的内容(*p)只读,不能改*p,但可改p的地址,安全合法。
int* const p = &val;//权限缩小 (无 const→限制地址),p的地址固定,不能改p,但可通过*p修改 val,安全合法。
const int* const p = &val;//权限缩小 (无 const→双限制),p的地址和指向的内容都只读,既不能改p,也不能改*p,安全合法。
第二种情况
int* p = &val;//权限放大 (const 内容→无 const),试图解除 val 的只读限制,编译器报错(discards 'const' qualifier),强行转换会导致未定义行为。
const int* p = &val;//权限对等(const 内容→const 内容),p指向的内容只读,可改p的地址,符合 const 规则
int* const p = &val;//权限放大 (const 内容→无 const 内容),虽限制了p的地址,但解除了内容的 const 限制,编译器报错,违反只读保护
const int* const p = &val//权限缩小 (const 内容→双限制),p的地址和指向的内容都只读,进一步加限制,安全合法。