尝试说透C语言指针

前言

不久以前尝试总结过《尝试说透C语言指针》的底稿,但觉得还是写的太复杂了,遂就放弃发布出去。
最近遇到一个事情,觉得void *类型是组织文字的一个比较好的抓手和切入点,以及增补有助理解的图表,就再次有兴趣将其共享出来:)

基本思想

在阅读严蔚敏经典的《数据结构》一书中,有句特别话,引起了我的重点关注,“对于递归,切记想的太深、太远”,我想这句话对于理解指针也是非常适用的。

最简指针形式

基础

任何变量均有地址

  • 指针变量作为变量

无论其是多少级的指针变量,其存储value的语义都是存储内存中的地址信息

  • 对指针解引用

无论其是多少级的指针变量,解引用此指针变量意味着从其存储的内存地址开始读写,且按照指针解引用的目标类型操作(也就是减少一级的类型),目标类型主要限定为读写多少个字节信息的内容。

图解指针

在这里插入图片描述

多级指针

Level说明
Type var零级,Type var变量
Type *Ptr一级,解引用获得Type var变量
Type **Ptr2二级,解引用获得Type *Ptr变量
Type ***Ptr3三级,解引用获得Type **Ptr2变量
貌似可以很多级,更难理解了;理解的金钥匙在于指针指向地址是否存在上一级指针类型变量?

图解多级指针

在这里插入图片描述

凶险的指针解引用

场景异常说明
悬空野指针读取的位置悬空就出现非法访问
按照某错误类型或约定类型读取过多的字节信息读取越界的非法访问

金钥匙void指针

指针作为存储内存地址变量,通常为机器字长度的字节信息,以利于能够存储内存中每个字节的地址信息,所以,指针类型相互赋值,可以没有任何字节信息损失,其sizeof都是同样大小的。

例如,作为万型void *,你可以将各类指针类型转化为void *,也可以将void *按照约定转化为对应类型。

同时,void *经常作为API接口的参数,是因为其不单可以作为某类型的万型指针,还可以变通使用为存储字节信息的容器,例如,整型等。

场景说明
int i ; void* pv = &i; int* pi = (int*)pv指针类型互转
void* pv = (void*)generic_var;作为容器存储变量的值

字节信息容器

typedef struct tagT_KeyInfo 
{
  uint8_t  bType;
  uint16_t wLen;
  union
   {
     uint8_t   data[5];
     uint16_t  wData;
     uint32_t  dwData;
   };
} __attribute__((packed)) T_KeyInfo;

int f(void *arg)
{
  //arg中存储keyInfo信息,所以,按照约定,用求地址运算得到T_KeyInfo的指针,然后解引用
  T_KeyInfo tKeyInfo = *(T_KeyInfo*)&arg;
  
  printf("Passed arg info: bType: %u, wLen: %u, wData: %u\n", tKeyInfo.bType, tKeyInfo.wLen, tKeyInfo.wData);
  
  return 0;
}

int main(int argc, char* argv[])
{
  printf("Hello world !\n");

  T_KeyInfo tKeyInfo = {};
  printf("Cannot convert to a pointer type from struct type!\n");
  //void* p3 = (void*)tKeyInfo;
   
  tKeyInfo.bType = 100;
  tKeyInfo.wLen  = sizeof(uint16_t);
  tKeyInfo.wData = 60000;
  
  /*
   * 指针作为字节容器,可以将机器字长度信息传入
   * 用求地址运算得到某类型的地址,如将其类型转化为void**,则解引用后就可以按照同类型操作,
   * 将字节信息装载到void*中
   */
  void* arg = *(void**)&tKeyInfo; 
  f(arg);
  
  printf("Exit from program !\n");
  return 0;
}

图解指针作为字节容器

在这里插入图片描述

void*指针作为信息容器为什么称其为精华

// assert(sizeof(VarType) == sizeof(void*))

 void* arg      = *(void\*\*)&var;
 
 //反向
 VarType var    = *(VarType*)&arg

体现C语言的语言特性,在很低硬件层次上可以根据内存地址读写内存,而且读写的语义随类型而变!

指针所指向的内存,如果真正存储了目标,则无惧各种指针操作了 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值