1.23 指针

一、指针定义

指针 本质上是一个变量,但它存储的不是普通数据(比如整数、字符),而是另一个变量在内存中的地址

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 *pp 指向 const int → 指向的 int 是只读(内容不能改)。

  • int *const pconst pint * → 指针 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的地址和指向的内容都只读,进一步加限制,安全合法。

相关推荐
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假5 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠6 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦13 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠14 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾14 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82114 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q14 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒14 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记14 天前
单项不带头不循环链表
数据结构·链表