当前位置: 首页 > news >正文

深入理解指针---1

(一)什么是指针

指针就是存放变量内存地址的变量 怎么理解呢

我们电脑的内存分为8GB,16GB,32GB等等,而内存也被划分成一个个的内存单元,每个内存单元的大小取一个字节,每个内存单元就相当于一个学生宿舍,一个字节空间里又能放8个比特位,就像我们宿舍是8人间,每个人是一个比特位,每个内存单元都有一个编号,就相当于宿舍的门牌号,而这个编号就等于地址等于指针

(二)取地址操作符&

在c语言中创建变量本质上就是向内存申请空间,比如创建一个整型变量如下

int a=10;

一个整型变量占4个字节,就是向内存申请了4个字节,每个字节都有自己的地址,如下所示

那么如何取到a的地址呢,这里我们就在需要用到取地址操作符&,&在之前使用scanf函数也是经常用到,表示取这个数据的地址 ,怎么将地址打印出来呢,这里需要用到之前学到的占位符%p,比如将上述整形a的地址打印出来,如下所示

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

这里整型a明明占了4个字节,为什么只打印出来一个地址,因为&a取出的是4个字节中地址较小的字节的地址

(三)指针变量的创建和类型

在上述过程中我们得到了a的地址,那么为了后续使用,怎么样将它存储起来,这时候我们就可以将它存储在指针变量中 如下所示

int a = 10; int* pa = &a;//取出a的地址,将其放入指针变量pa中

那么上述代码中的指针变量类型是什么,首先pa左边的int*,它在常规的整型变量中加了一个*,而*就表示pa是指针变量,而前面的int指pa指向的a是一个整型类型 那如果有一个char类型的b,那么该如何创建指针变量呢?如下所示

char b='a'; char*pc=&b;//取出字符b的地址,将其放入指针变量pc中

(四)指针变量的使用

我们通过指针变量将地址给存储起来,那么又该如何使用呢? 这时候我们就需要用到解引用操作符*,具体操作如下所示

int a = 10; int* pa = &a; *pa;//解引用,通过pa中存放的地址,找到指向的空间,所以这里的*pa就相当于a printf("%d", *pa);

打印出来的*pa就是a的值

也可以通过修改*pa的值来修改a的值,如下所示

可以看出,不仅*pa的值变成199,a的值也同样修改为199

(五)指针变量类型的意义

1.指针的解引用

下面我们通过两段代码来理解指针变量的意义

int a = 0x11223344;//整型a存放的是16进制的数字 int* pa = &a; * pa = 0;将整型a的4个字节改成0

原来a在内存中存放的值如下

修改完之后如下

可以看出将4个字节全部修改成0

然而当我们创建char类型的变量时

int a = 0x11223344; char* pa = (char*) & a; * pa = 0;

可以看出只能将a的第一个字节改成0

所以指针的类型决定了指针解引用时的权限,char*类型就只能访问一个字节,而int*类型的指针就可以访问4个字节

2.指针+-整数

通过上述的例子我们可以得知指针类型的不同,访问的字节也不同,我们可以再举一例,如下方代码

int a = 10; int* pa = &a; char* pc = (char*)&a; printf("&a=%p\n", &a); printf("pa=%p\n", pa); printf("pa+1=%p\n", pa+1); printf("pc=%p\n", pc); printf("pc+1=%p\n", pc+1);

我们可以看出,char类型的指针+1之后在原来的基础上地址只变化了一位,而int类型的指针+1之后则在原来的基础上变化了4位,所以可以得知,指针的类型决定了指针变化了多少位。

那么我们可以再做个练习,用指针将数组中的元素依次打印出来,如下代码所示

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; int* pa = &arr[0]; for (i = 0; i < sz; i++) { printf("%d ", *(pa + i)); }

pa表示的是取的是arr数组中第一个元素的地址,那我们只需要依次求出arr数组中元素的地址,再使用解引用符号*,我们就可以依次得出arr数组中的元素

3.指针+-指针

用以下代码举例

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* pa = &arr[0]; int* pc = &arr[9]; printf("%d", pc-pa);

指针-指针最终得到的结果就是两个指针(地址)之间的元素个数

⚠️:指针+-指针必须指向的是同一内存空间,像上方的代码中,指向的都是arr数组,下方代码为错误示范

int arr[4] = { 1,2,3,4 }; char b = 'e'; int* pa = &arr[2]; char* pc = &b; printf("%d", pc - pa);

我们可以用指针-指针来求字符串长度,在之前,不用指针如何求字符串长度的呢,我们需要用到strlen函数,并且strlen函数的返回值是size_t,且需要头文件<string.h>,如下所示

#include <stdio.h> #include <string.h> int main() { char ch[] = "abcde"; size_t len = strlen(ch); printf("%d", len); return 0; }

那么我们现在知道指针-指针就是两个指针之间的元素个数,那么我们可以分别求出字符串长度中第一个元素的地址,和’/0’的地址,将两个指针(地址)相减,就能得到字符串长度了,如下代码所示

size_t my_strlen(char* p)//指针接受参数 { char* start = &p[0];//start取ch数组第一个元素的地址 while (*p != '\0') { p++; } //p最终变成\0的地址 return p - start; } int main() { char ch[] = "abcde"; size_t len = my_strlen(ch);//函数传递的是ch数组,其实ch又代表ch数组中第一个元素的地址 printf("%d", len); //所以传递的是地址,需要用指针来接受参数 return 0; }
4.指针的关系运算

两个指针比较大小,我们依旧拿我们最熟悉的题目举例,打印出数组中的每个元素,如下代码所示

int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); int* pa = arr; int* pc = &arr[sz]; while (pa < pc) { printf("%d ", *pa); pa++; } return 0; }

上述代码中,pa表示第一个元素的地址,而pc表示数组中的第十个元素的后一位的地址,不是数组内的,所以当pa<pc时,解引用打印出元素,再通过pa++,依次打印后面的元素

http://www.gsyq.cn/news/1528566.html

相关文章:

  • 掌控板OLED显示不亮?手把手教你排查SH1106与SSD1306的库冲突问题
  • 保姆级教程:在Vue+Element-UI项目里优雅管理所有弹窗的层级(附完整代码)
  • GW INSTEK GPP-4323网络控制踩坑记:解决PyVISA连接超时与指令无响应的几个关键点
  • 数据科学落地七宗罪:从模型到业务价值的实战避坑指南
  • 告别混乱配置:在Flask/Django项目中优雅管理config.py(附解决导入错误的实战技巧)
  • 2026年浙江定制集装箱处置方案深度测评:技术路径、成本控制与落地案例全解析 - 优质品牌商家
  • 解决CH32V307以太网项目痛点:DHCP网线热插拔与IP耗尽问题的LwIP底层修改详解
  • 手把手调试USB PD:用逻辑分析仪抓包分析Reset全过程(附Wireshark配置)
  • 宁德市五家靠谱店铺TOP排行榜及联系方式地址+黄金回收门店推荐 电话+白银回收+铂金回收+彩金回收当场结算 - 盛世金银回收
  • 避开这些坑!Arduino驱动42步进电机时,TB6600接线与代码的5个常见误区
  • 生产环境避坑实录:银河麒麟服务器bond双网卡绑定后,网络延迟飙升怎么办?
  • 荆州市黄金回收门店推荐 五家靠谱店铺TOP排行榜及联系方式地址电话+白银回收+铂金回收+彩金回收当场结算 - 大熊猫898989
  • P1342 请柬【洛谷算法习题】
  • Python代码考古学:逆向工程工作流实战指南
  • LaTeX图表标题里引用文献顺序乱了?试试这个bibtex宏包,亲测有效
  • 科来抓包时提示‘没有足够的缓存’?别慌,这份避坑指南教你快速解决并开始分析
  • 给Agent攒评测用例,我是这么从零搞起来的
  • 广安市黄金回收门店推荐 五家靠谱店铺TOP排行榜及联系方式地址电话+白银回收+铂金回收+彩金回收当场结算 - 大熊猫898989
  • 从EEPROM读写失败讲起:深度解析STM32 I2C_AF、OVR等错误标志位的排查与恢复
  • 避开这些坑!Uibot RPA实施工程师认证实践题保姆级避坑指南
  • GitLab启动慢到网页报错?别急着重启,先看看你的服务器内存够不够
  • VIO初始化避坑指南:为什么你的OpenVINS总是初始化失败?从原理到调参全解析
  • SAP STO交货单创建后库位丢失?手把手教你用BAPI_OUTB_DELIVERY_CHANGE补救(附ABAP代码)
  • 便宜产品摄影哪家性价比高? - 工业品牌热点
  • 广元市黄金回收门店推荐 五家靠谱店铺TOP排行榜及联系方式地址电话+白银回收+铂金回收+彩金回收当场结算 - 大熊猫898989
  • 广州市黄金回收门店推荐 五家靠谱店铺TOP排行榜及联系方式地址电话+白银回收+铂金回收+彩金回收当场结算 - 大熊猫898989
  • 承德市黄金回收门店推荐 五家靠谱店铺TOP排行榜及联系方式地址电话+白银回收+铂金回收+彩金回收当场结算 - 大熊猫898989
  • MCP2515配置避坑指南:从SPI时序到中断处理,那些手册里没细说的实战经验
  • 2026年私立普高怎么联系,靠谱的招生渠道与费用盘点 - 工业品牌热点
  • 手把手教你用TiggerRamDisk绕过iPhone/iPad激活锁(支持iOS16.3,Win7/Win10/Mac教程)