深入理解 C 语言指针
指针
程序
代码
#include<stdio.h>
void charPtTest() {
// 声明一级指针
char *p1;
char *p2;
char *p3;
// 利用字符串初始化一级指针:将一级指针指向字符串首地址
// 获取地址 By & (取地址运算符)↑
// 强制类型转换(可选)
p1 = (char *) &"Hello";
// 利用一级指针初始化一级指针:将一级指针的值赋给一级指针,本质上就是两个一级指针指向同一个地址
// 获取地址 By 直接赋值 ←
p2 = p1;
// 利用字符串初始化一级指针:将一级指针指向字符串首地址
// 获取地址 By & ↑(缩写形式)
p3 = "Hello";
printf("字符串常量的值:%s\n", "Hello");
printf("字符串常量的地址:%p\n", "Hello");
printf("\n");
printf("一级指针\n");
// 按照字符串形式打印一级指针的值,就是按照字符串形式打印一级指针中存储的地址,即字符串常量的地址
// 按照指针形式打印一级指针的值,就是按照指针形式打印一级指针中存储的地址,即字符串常量的地址
// 打印的对象都是一级指针的值,即字符串常量的地址,因为是字符串常量,所以支持两种不同的输出格式
printf("p1 的值: %s %p\n", p1, p1);
printf("p1 的地址: %p\n", &p1);
printf("p2 的值: %s %p\n", p2, p2);
printf("p2 的地址: %p\n", &p2);
printf("p3 的值: %s %p\n", p3, p3);
printf("p3 的地址: %p\n", &p3);
// 声明二级指针,同时给二级指针赋值,二级指针的值就是一级指针的地址
// 获取地址 By & ↑
char **pp1 = &p1;
char **pp2 = &p2;
char **pp3 = &p3;
printf("\n");
// 二级指针的值就是一级指针的地址
// 因为二级指针存储的是地址,所以只能按照指针形式打印二级指针的值,而不能按照字符串形式打印
printf("二级指针\n");
printf("pp1 的值: %p\n", pp1);
printf("pp1 的地址: %p\n", &pp1);
printf("pp2 的值: %p\n", pp2);
printf("pp2 的地址: %p\n", &pp2);
printf("pp3 的值: %p\n", pp3);
printf("pp3 的地址: %p\n", &pp3);
printf("\n");
printf("一级指针\n");
// 声明一级指针
char *str1;
// 利用二级指针初始化一级指针
// 获取二级指针的值(一级指针的地址) By * (取值运算符)↓
str1 = *pp1;
printf("str1 的值:%s %p\n", str1, str1);
printf("str1 的地址:%p\n", &str1);
// 利用强制类型转换初始化一级指针
char *p_str1 = (char *) pp1;
// 因为二级指针存储的是地址,所以只能按照指针形式打印二级指针的值,而不能按照字符串形式打印
// 此处强行通过类型转换将二级指针变成一级指针,能打印,但是打印结果是乱码
printf("p_str1 的值:%s %p\n", p_str1, p_str1);
printf("p_str1 的地址:%p\n", &p_str1);
printf("\n");
printf("常量\n");
// 获取指针的值 By * ↓
// 获取一级指针的值(字符串首地址):第一个字符
char ch = *p1;
printf("ch 的值: %c\n", ch);
printf("ch 的地址: %p\n", &ch);
}
int main() {
charPtTest();
return 0;
}
结果
字符串常量的值:Hello
字符串常量的地址:0x104e1fdc4
一级指针
p1 的值: Hello 0x104e1fdc4
p1 的地址: 0x16afe3800
p2 的值: Hello 0x104e1fdc4
p2 的地址: 0x16afe37f8
p3 的值: Hello 0x104e1fdc4
p3 的地址: 0x16afe37f0
二级指针
pp1 的值: 0x16afe3800
pp1 的地址: 0x16afe37e8
pp2 的值: 0x16afe37f8
pp2 的地址: 0x16afe37e0
pp3 的值: 0x16afe37f0
pp3 的地址: 0x16afe37d8
一级指针
str1 的值:Hello 0x104e1fdc4
str1 的地址:0x16afe37d0
p_str1 的值:��� 0x16afe3800
p_str1 的地址:0x16afe37c8
常量
ch 的值: H
ch 的地址: 0x16afe37c7
int 的值: 1
int 的地址: 0x16afe37b4
关系图
引用关系
基于结果整理引用关系
赋值关系
基于程序整理复制关系
合并
合并引用关系图和赋值关系图
总结
-
指针赋值手段
-
正统做法
二级指针 * ↓ 取值 一级指针 ← 赋值 一级指针 & ↑ 取地址 变量
- 二级指针取值:取值后的到二级指针指向的一级指针的指向,将该指向赋给一级指针
- 一级指针赋值:两个一级指针指向同一片内存空间,但是两个一级指针的地址不同
- 变量取地址:获取变量首地址,将一级指针指向该地址
-
强制类型转换:所有指针存的都是地址,可用通过强制类型转换
二级指针 赋值 By 强类型转换 → 一级指针
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏