一篇足以理解指针到底是何方神圣

一篇足以理解指针到底是何方神圣,第1张

一篇足以理解指针到底是何方神圣

以下文章来源于:公_众_号开源电子网
读取更多技术文章,请扫码关注

什么是指针:
指针你真正了解吗?那么你懂得计算机内存是如何存储吗,如果你真正了解指针到底是是什么,那么你就会懂得计算机内存是如何存储的。
首先了解指针之前,我们必须了解计算机内存是如何存储的,一般的32位计算机把内存分割为字节,一般32位的机器int类型为32比特,也就是4字节,一字节有8bit数据,这个必须知道的知识点,如以下图所示:

上图可知:一个字节8bit的数据,所以计算机为了区分内存的每一个字节,那么计算器给它们进行排号,而这些号就是地址 ,例如学校的宿舍,每一间的宿舍住了八个人,宿舍必定有一个宿舍号,所以舍管阿姨会对宿舍号进行查找的某宿舍人员的原理类似。

上图可知,一般来说int型变量有4字节,所以每一个地址偏移4个字节,如果指针P指向0x20000004地址,那么该地址存储的值就是0x82。

C语言指针是什么

上面我们已经了解计算机内存是如何存储以及如何读取地址的值,显然小编是举32位的计算机就是为了方便我们学习MCU,因为MUC大部分也是32位的。
C语言指针可以简化一些C编程任务执行的任务,例如动态内存分配,如果没有指针那么无法执行的,所以成为C程序员或者嵌入式工程师,学习指针很有必要的。
数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。在学习C语言时候,变量都有一个内存位置,那么它们可以使用“&”运算符访问地址,表示它在内存中的一个地址。如以下源码所示:

#include 

 
int main ()
{
   
   int  lv_variate = 10;
   
   int  *ip_variate; 
   
   ip_variate = &lv_variate;  
 
   printf("lv_variate 变量的地址: %pn", &lv_variate  );
 
   
   printf("ip_variate 指针变量存储的地址: %pn", ip_variate );

    
   printf("ip_variate 指针变量的地址: %pn", &ip_variate );

   
   printf("*ip_variate 变量的值: %dn", *ip_variate );
 
   return 0;
}
串口调式助手输出他们的打印信息,如以下所示:、
lv_variate 变量的地址: 20000784
ip_variate 变量存储的地址: 20000784
ip_variate 指针变量的地址: 20000780
*ip_variate 变量的值: 10
我们怎么理解上述输出的信息呢?,可以使用示意图来解析上述的信息,如图所示:

总结:
①变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符
②“&” 运算符访问地址
③*ip_variate就是读取指针变量存储的地址对应的值(20000784的地址的值10)
④ip_variate读取指针变量存储的地址
小知识:
如果程序被编译和链接后,使用 * ip_variate 的话,要先通过地址 20000780取得变量 ip_variate 本身的值,这个值是变量 lv_variate 的地址,然后再通过这个值取得变量 lv_variate 的数据,前后共有两次步奏;而使用 lv_variate 的话,可以通过地址 20000784直接取得它的数据,只需要一步运算。
可以这样说,使用指针是间接获取数据,使用变量名是直接获取数据。
什么是二级指针:
上面我们以及理解什么是指针以及一级指针的 *** 作,如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
二级指针是指向一级指针的指针。二级指针指向一级指针,也就是二级指针中存储的是一级指针的内存地址。

二级指针的使用:
int  main( void )
{
     int  a = 10;                           		//声明一个变量a
     int  *p = &a;                          		//声明指针p,指向变量a
     int  **q = &p;                         		//声明二级指针q,指向一级指针p
     printf ( "a = %dn" ,a);               	//打印变量a的值
     printf ( "a的地址&a=%pn" ,&a);        	//打印变量a的地址
     printf ( "p = %pn" ,p);               	//打印p的值
     printf ( "p的地址&p=%pn" ,&p);        	//打印p的地址
     printf ( "p的解引用*p=%dn" ,*p);      	//打印p的解引用
     printf ( "q = %pn" ,q);               	//打印q的值
     printf ( "q的地址&q=%pn" ,&q);        	//打印q的地址
     printf ( "q的解引用*q=%pn" ,*q);      	//打印q的解引用
     printf ( "q的双重解引用**q=%dn" ,**q);	//打印q的双重解引用
     return  0;
}
执行结果:
a = 10
a的地址&a=20000788
p = 20000788
p的地址&p=20000784
p的解引用*p=10
q = 20000784
q的地址&q=20000780
q的解引用*q=20000788
q的双重解引用**q=10
我们怎么理解上述输出的信息呢?,可以使用示意图来解析上述的信息,如图所示:

总结:

① 变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符
② “&” 运算符访问地址
③ q读取指针变量存储的地址(0x20000784)
④ *q读取指针变量存储的地址的对应的值(就是一级指针变量存储的地址(0x20000788))
⑤ **q读取指针变量存储的地址的对应的值的对应地址的值(就是一级指针变量存储的地址(0x20000788)对应的值(10))

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5097534.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-16

发表评论

登录后才能评论

评论列表(0条)

保存