news 2026/2/10 10:12:45

第11讲:深入理解指针(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第11讲:深入理解指针(一)

目录:

1.内存和地址
2.指针变量和地址
3.指针变量类型的意义
4.指针运算
———————————————————————————————————————————

1.内存和地址

1.1内存

我们知道计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,那我们买电脑的时候,电脑上内存是 8GB/16GB/32GB 等,那这些内存空间如何高效的管理呢?

其实也是把内存划分为⼀个个的内存单元,每个内存单元的大小取1个字节。
计算机中常见的单位(补充):
⼀个比特位可以存储⼀个2进制的位1或者0
1Byte = 8bit 1KB = 1024Byte 1MB = 1024KB 1GB = 1024MB 1TB = 1024GB 1PB = 1024TB
其中,每个内存单元,相当于⼀个学生宿舍,⼀个字节空间里面能放8个比特位,就好比同学们住
的八人间,每个人是⼀个比特位。
每个内存单元也都有⼀个编号(这个编号就相当于宿舍房间的门牌号),有了这个内存单元的编
号,CPU就可以快速找到⼀个内存空间。
生活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也称为地址。C语言中给地址起
了新的名字叫:指针。

1.2究竟该如何理解编址

CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而因为内存中字节
很多,所以需要给内存进行编址(就如同宿舍很多,需要给宿舍编号⼀样)。
计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。

2.指针变量和地址

2.1取地址操作符(&)

理解了内存和地址的关系,我们再回到C语言,在C语言中创建变量其实就是向内存申请空间

#include <stdio.h> int main() { int a = 10; &a;//取出a的地址 printf("%p\n", &a); return 0; }

这样就可以打印出a的地址,&a取出的是a所占4个字节中地址较小的字节的地址。

2.2指针变量和解引用操作符(*)

2.2.1指针变量
那我们通过取地址操作符(&)拿到的地址是⼀个数值,比如:0x006FFD70,这个数值有时候也是需要存储起来,方便后期再使用的,那我们把这样的地址值存放在哪里呢?答案是:指针变量中。
例:
#include <stdio.h> int main() { int a = 10; int * pa = &a;//取出a的地址并存储到指针变量pa中 return 0; }
指针变量也是⼀种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
2.2.2如何拆解指针类型
我们看到pa的类型是int*,我们该如何理解指针的类型呢?
int a = 10; int * pa = &a;
这里pa左边写的是int**是在说明pa是指针变量,而前面的int是在说明pa指向的是整型(int)
类型的对象。

⼀个char类型的变量ch,ch的地址,要放在什么类型的指针变量中呢?

char ch = 'w'; char* pc = &ch; // pc 是指向 char 类型的指针
2.2.3解引用操作符
C语言中其实也是⼀样的,我们只要拿到了地址(指针),就可以通过地址(指针)找到地址(指针) 指向的对象,这里必须学习⼀个操作符叫解引⽤操作符(*)。
#include <stdio.h> int main() { int a = 100; int* pa = &a; *pa = 0; return 0; }
上面代码中第7行就使用了解引用操作符,*pa就是通过pa中存放的地址,找到指向的空间, *pa其实就是a变量了;所以*pa = 0,这个操作符是把a改成了0。
但这里如果目的就是把a改成0的话,写成a = 0;不就完了,为啥非要使用指针呢?
其实这里是把a的修改交给了pa来操作,这样对a的修改,就多了⼀种的途径,写代码就会更加灵活,后期就能理解了。

2.3指针变量的大小

如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以。
同理64位机器,假设有64根地址线,⼀个地址就是64个二进制位组成的二进制序列,存储起来就需要
8个字节的空间,指针变量的大小就是8个字节。
#include <stdio.h> //指针变量的⼤⼩取决于地址的⼤⼩ //32位平台下地址是32个bit位(即4个字节) //64位平台下地址是64个bit位(即8个字节) int main() { printf("%zd\n", sizeof(char *)); printf("%zd\n", sizeof(short *)); printf("%zd\n", sizeof(int *)); printf("%zd\n", sizeof(double *)); return 0; }

32位操作系统下运行结果 64位操作系统下运行结果
结论:

32位平台下地址是32个bit位,指针变量大小是4个字节
64位平台下地址是64个bit位,指针变量大小是8个字节
注意指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的。

3.指针变量类型的意义

3.1指针的解引用
//代码1 #include <stdio.h> int main() { int n = 0x11223344; int *pi = &n; *pi = 0; return 0; }
//代码2 #include <stdio.h> int main() { int n = 0x11223344; char *pc = (char *)&n; *pc = 0; return 0; }

对比两个代码的运行结果,可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第⼀个字节改为0。

结论:char*的指针解引用就只能访问⼀个字节,而int*的指针的解引用就能访问四个字节

3.2指针+-整数

运行下面的代码,观察输出结果中地址的变化:

#include <stdio.h> int main() { int n = 10; char *pc = (char*)&n; int *pi = &n; printf("%p\n", &n); printf("%p\n", pc); printf("%p\n", pc+1); printf("%p\n", pi); printf("%p\n", pi+1); return 0; }

我们可以看出,char*类型的指针变量+1跳过1个字节,int*类型的指针变量+1跳过了4个字节。
(int跳过一个整形变量所以是四个字节)
结论:指针的类型决定了指针向前或者向后走⼀步有多大(距离)

3.3void* 指针

在指针类型中有⼀种特殊的类型是void * 类型的,可以理解为无具体类型的指针,

void*类型的指针不能直接进行指针的+ - 整数和解引用的运算。

例:

#include <stdio.h> int main() { int a = 10; int* pa = &a; char* pc = &a; return 0; }
在上⾯的代码中,将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。编译器给出了⼀个警告(如下图),是因为类型不兼容。而使用void*类型不会出现这样的问题。
使用void*类型的指针接收地址:
#include <stdio.h> int main() { int a = 10; void* pa = &a; void* pc = &a; *pa = 10; *pc = 0; return 0; }
通过编译我们可以看到,void*类型的指针可以接收不同类型的地址,但是无法直接进行指针运算。
⼀般void*类型的指针是使用在函数参数的部分,来接收不同类型数据的地址,可以实现泛型编程的效果。使得⼀个函数来处理多种类型的数据,在后文中会深入理解。

4.指针运算

指针的基本运算有三种,分别是:
指针+- 整数
指针-指针
指针的关系运算

4.1指针+- 整数

int arr[10] = {1,2,3,4,5,6,7,8,9,10};

#include <stdio.h> //指针+- 整数 int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = &arr[0]; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); for (i = 0; i < sz; i++) { printf("%d ", *(p + i));//p+i 这⾥就是指针+整数 } return 0; }

4.2指针 - 指针

//指针-指针 #include <stdio.h> int my_strlen(char* s) { char* p = s; while (*p != '\0') p++; return p - s; } int main() { printf("%d\n", my_strlen("abc")); return 0; }

4.3指针的关系运算

//指针的关系运算 #include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = &arr[0]; int sz = sizeof(arr) / sizeof(arr[0]); while (p < arr + sz) //指针的⼤⼩⽐较 { printf("%d ", *p); p++; } return 0; }

———————————————————————————————————————————

JohnWick

2026.1.19

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/9 6:03:21

如何用Trilium中文版打造个人知识管理系统

如何用Trilium中文版打造个人知识管理系统 【免费下载链接】trilium-translation Translation for Trilium Notes. Trilium Notes 中文适配, 体验优化 项目地址: https://gitcode.com/gh_mirrors/tr/trilium-translation 还在为知识碎片化而烦恼吗&#xff1f;面对海量的…

作者头像 李华
网站建设 2026/1/30 3:24:41

ImageGlass图像浏览工具终极指南:从菜鸟到高手的全面解析

ImageGlass图像浏览工具终极指南&#xff1a;从菜鸟到高手的全面解析 【免费下载链接】ImageGlass &#x1f3de; A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass 你是不是也遇到过这样的尴尬场景&#xff1a;下载了一…

作者头像 李华
网站建设 2026/2/6 20:10:28

Qwen3-1.7B在金融问答中的实际应用,落地方案详解

Qwen3-1.7B在金融问答中的实际应用&#xff0c;落地方案详解 1. 引言&#xff1a;金融场景下的大模型需求与挑战 随着金融科技的快速发展&#xff0c;金融机构对自动化、智能化服务的需求日益增长。从智能客服到投资顾问&#xff0c;从风险评估到合规审查&#xff0c;自然语言…

作者头像 李华
网站建设 2026/2/6 1:22:55

BetterGI智能助手:原神游戏自动化操作的全新解决方案

BetterGI智能助手&#xff1a;原神游戏自动化操作的全新解决方案 【免费下载链接】better-genshin-impact &#x1f368;BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动派遣 | 一键强化 - UI Automation Testing Tools For …

作者头像 李华
网站建设 2026/2/8 17:28:10

零代码启动中文情感分析|StructBERT镜像一键部署指南

零代码启动中文情感分析&#xff5c;StructBERT镜像一键部署指南 1. 背景与应用场景 在当前自然语言处理&#xff08;NLP&#xff09;的实际应用中&#xff0c;中文情感分析已成为企业洞察用户反馈、监控舆情、优化客服系统的重要技术手段。传统实现方式通常需要搭建深度学习…

作者头像 李华
网站建设 2026/2/7 1:10:26

ModelScope镜像推荐:Qwen1.5-0.5B-Chat开箱即用测评

ModelScope镜像推荐&#xff1a;Qwen1.5-0.5B-Chat开箱即用测评 1. 引言 随着大模型技术的快速发展&#xff0c;轻量级、可本地部署的对话模型正逐渐成为开发者和中小型企业构建智能服务的重要选择。在众多开源模型中&#xff0c;阿里通义千问系列推出的 Qwen1.5-0.5B-Chat 凭…

作者头像 李华