深入理解指针1
发布时间:2026/9/28 12:20:43 锦皓数字建站

1.什么是指针1.1指针概念本质上指针就是地址口语中所说的指针其实就是指针变量指针变量是用来存放地址的一个指针。1.2内存和地址cpu中央处理器在处理数据时需要的数据在内存中读取处理后的数据也会放回内存中那这些内存空间如何高效管理呢其实也是把内存划分为⼀个个的内存单元每个内存单元的⼤⼩取1个字节每个内存单元都有一个编号有了这个内存单元的编 号CPU就可以快速找到⼀个内存空间。编号就相当于地址地址即指针。内存单元的编号地址指针1.3如何理解编址计算机中的编址并不是把每个字节的地址记录下来⽽是通过硬件设计完成的。32位机器有32根地址总线 每根线只有两态表⽰0,1【电脉冲有⽆】那么 ⼀根线就能表⽰2种含义2根线就能表⽰4种含 义依次类推。32根地址线就能表⽰2^32种含 义每⼀种含义都代表⼀个地址2.指针变量和地址2.1取地址操作符创建变量的本质是向内存申请空间上述代码就是创建了整形变量a向内存申请了4个字节用于存放整数10其中每个字节都有地址上图中4个字节的地址分别是0x000000D8686FF914 —— 0a //10 内存中数据是以16进制的形式展示的0x000000D8686FF915 —— 00 而且是倒着展示的0x000000D8686FF916 —— 000x000000D8686FF917 —— 00那么如何得到a的地址呢通过取地址操作符 - int main() { int a 10; a;//取出a的地址 printf(%p\n, a);//0x000000D8686FF914 return 0; }注%p是专门用来打印地址的地址是数值每次调试a的地址都不一样2.2指针变量和解引用操作符 *2.2.1指针变量我们通过取地址操作符拿到的地址是一个数值比如0x006FFD70这个数值有时候也需要存储起来方便后期使用那么把这样的地址放在哪里呢答案是指针变量中int main() { int a 10; int* p a;//取出a的地址并存储到指针变量p中p就是指针变量 // int* p 也可以写成 int *p / int * p //注意这里的 * 不是解引用操作符只是表示你声明的变量是一个指针类型 }指针变量也是一种变量这种变量就是用来存放地址的存放在指针变量中的值都会理解为地址。即变量a和指针变量p都有各自的地址p中存放的是a的地址。如何拆解指针类型2.2.2解引用操作符*我们将地址保存起来未来是要使⽤的那怎么使⽤呢我们只要拿到了地址指针就可以通过地址指针找到地址指针 指向的对象这⾥要学习⼀个操作符叫做解引⽤操作符(*)。int main() { int a 100; int* p a; printf(a%d\n, *p);//这里 * 是解引用操作符*p的意思是通过p里存放的地址找到p所指向的对象也就是a所以*p就是a //*pa *p 10;//改变的是a的值 printf(a%d\n, a);//10 printf(%p\n, a);//a的地址 printf(%p\n, *p);//a的地址 printf(%p\n, p);//a的地址p是指针变量 printf(%p\n, p);//p自己的地址 return 0; }解引用操作符 * 的作用就是通过变量里存放的地址找到p所指向的对象上述例子中p里存放着a的地址指向a所以 *p 指向 a 所以 *p a2.3指针变量的大小前⾯的内容我们了解到32位机器假设有32根地址总线每根地址线出来的电信号转换成数字信号后 是1或者0那我们把32根地址线产⽣的2进制序列当做⼀个地址那么⼀个地址就是32个bit位需要4 个字节才能存储指针变量的大小 - 取决于存放的是什么 - 是地址 - 地址的存放需要多大空间 - 32(64)位机器上地址是32(64)个比特位需要4(8)个字节的空间才能存储 -一个指针变量的大小是4(8)个字节总结指针变量的大小跟类型无关3.指针变量类型的意义虽然指针变量的⼤⼩和类型⽆关但指针类型有特殊意义3.1指针的解引用这是一段将 a1 a2 的值改为 0 的代码上面那段代码指针变量的类型是 int* 最终输出结果为 0 下面那段代码指针变量的类型是 char* 最终却输出了 287453925 这是因为 char* 的指针解引用就只能访问1个字节a2就变成了 00 33 22 11而int*的指针解引用就能访问4个字节结论指针变量的类型决定了对指针进行解引用时有多大权限3.2指针-整数int main() { int a 0x11223344; int* pi a; char* pc a; printf(%p\n, pi);//0000002E9DD8F984 printf(%p\n, pi1);//0000002E9DD8F988 增加了4个字节 printf(%p\n, pc);//0000002E9DD8F984 printf(%p\n, pc1);//0000002E9DD8F985 增加了1个字节 return 0; }可以看到char* 类型的指针变量1跳过1个字节 int* 类型的指针变量1跳过了4个字节结论指针类型决定了指针向前或向后走一步走多大3.3void*指针在指针类型中有⼀种特殊的类型是 void * 类型的可以理解为⽆具体类型的指针或者叫泛型指 针这种类型的指针可以⽤来接受任意类型地址但其也有局限性void* 类型的指针不能直接进行指针的 - 和解引用可以强制类型转换4.指针运算指针 - 整数 指针指针 - 指针 整数指针的关系运算指针之间可以比较大小指针 指针 无意义4.1指针 - 整数因为数组在内存中是连续存放的只要知道第⼀个元素的地址顺藤摸⽠就能找到后⾯的所有元素//指针整数 int main() { int arr[] { 1,2,3,4,5,6,7,8,9,10 }; int* p arr[0]; int i 0; for (i 0;i 10;i) { printf(%d , *(p i));//打印数组元素 printf(%p , p i);//数组元素的地址 printf(\n); } return 0; }//指针-整数 int main() { int arr[] { 1,2,3,4,5,6,7,8,9,10 }; int* p arr[9]; int i 0; for (i 0;i10;i) { printf(%d , *(p - i));//降序打印数组元素 } return 0; }注下面这段代码也能打印数组中的元素但是p的值会变最好在 p 用完之后再初始化int main() { int arr[] { 1,2,3,4,5,6,7,8,9,10 }; int* p arr[0]; int i 0; for (i 0;i 10;i) { printf(%d , *p); p;//变的是p } *p arr[0];//再初始化p return 0; }4.2指针 - 指针但下面这种写法是错误的两个指针指向的不是同一块空间无法得到准确结果结论指针 - 指针 指针之间的元素个数指针 - 指针的前提是两个指针指向同一块空间4.3指针的关系运算指针可以进行 ! 的比较指针就是地址编号编号是一个数值可以比较大小int main() { int arr[] { 1,2,3,4,5,6,7,8,9,10 }; int* p arr; while (p arr[10]) { printf(%d , *p); p; } return 0; } //最终输出 1 2 3 4 5 6 7 8 9 105.小练习用指针相关知识写一个函数实现strlen()函数的效果int my_strlen(char* p)//数组传参时传过来的是数组首元素的 地址 不是数组所以这里可以写成指针的形式这里不要用sizeof来实现代码 { char* start p;//p一开始是首元素的地址 while (*p ! \0)//字符串结尾有\0当遇见\0时说明字符串中的字符已经读完了可以停止循环它的ASCII码值是0所以可以这么写while*p) { p;//读完一个字符地址就 1 } return p - start;//用 指针 - 指针就能得到指针之间的整数个数用最后一个元素的地址 - 首元素的地址就是字符串中字符的个数 } int main() { char ch[100] abcdef; int len my_strlen(ch); printf(%d\n, len); return 0; }
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。