C语言双指针的用法

参考 https://blog.csdn.net/dissection_c 书籍

1、数组的内存布局

1.1 一维数组

 int a[5];
 一个包含了5个 int型的数组,可以用a[0],a[1]等来访问数组里面的每一个元素。
在这里插入图片描述
 sizeof(a) = sizeof(int) *5 ,32位系统下为20.
 sizeof(a[0]) = sizeof(int),32位系统下为4
 sizeof(&a[0]) = 4,取元素a[0]的首地址
 sizeof(&a) = 4, 取数组a的首地址

1.2 二维数组

在这里插入图片描述
实际上内存不是表状的,而是线状的,那二维数组在内存里面肯定也是线性存储的。
在这里插入图片描述
 a[3][4]可以分成3组,a[0]、a[1]、a[2],每组有4个元素,因此可以计算各组的首地址
 a[0] 的地址:&a[0]
 a[1] 的地址:&a[0] + 1*sizeof(char)4
 a[2] 的地址:&a[0] + 2
sizeof(char)4
 a[i][j] 的地址 &a[0] + i
sizeof(char)4 +jsizeof(char)

2、二级指针

 char **p;
 p 是一个二级指针变量,在32位系统下占4个byte.它与一级指针不同的是,一级指针保存的是数据的地址,二级指针保存的是一级指针的地
址。
在这里插入图片描述
 给变量P初始化
 A), p=NULL;
 B), char * p2 p = &p2
 当我们真正需要使用 p 的时候,就必须把一个一级指针的地址保存到 p 中,所以 B)的
赋值方式也是正确的。
 给 p 赋值没有问题,但怎么使用 p 呢?这就需要我们前面多次提到的钥匙(“”)。
第一步:根据 p 这个变量,取出它里面存的地址。
第二步:找到这个地址所在的内存。
第三步:用钥匙打开这块内存,取出它里面的地址,p 的值。
第四步:找到第二次取出的这个地址。
第五步:用钥匙打开这块内存,取出它里面的内容,这就是我们真正的数据,**p 的值。
我们在这里用了两次钥匙(“
”)才最终取出了真正的数据。也就是说要取出二级指针
所真正指向的数据,需要使用两次两次钥匙(“
”)。

3、二级指针举例

typedef struct {
    UINT8                       Segment;
    UINT8                       Bus;
    UINT8                       Device;
    UINT8                       Function;
} DEVICE_BDF;

typedef struct {
    UINT8                       SlotNumber;
    UINT8                       CpuId;
    UINT8                       HotplugSupport;
    DEVICE_BDF                  DeviceBdf;
} DEVICE_REPORT_SLOT_INFO;

DEVICE_REPORT_SLOT_INFO             *RISER_PCIE_REPORT_TABLE;

DEVICE_REPORT_SLOT_INFO *RISER_PCIE_REPORT_TABLE 可理解成

DEVICE_REPORT_SLOT_INFO RISER_PCIE_REPORT_TABLE[] = {
{1, 1, FALSE, {04,00,01,00}},
{2, 1, FALSE, {01,00,01,00}},
{3, 1, FALSE, {01,00,03,00}},
}
数组RISER_PCIE_REPORT_TABLE共有三组,每组都是DEVICE_REPORT_SLOT_INFO结构体类型
RISER_PCIE_REPORT_TABLE 的大小为 sizeof(DEVICE_REPORT_SLOT_INFO ) 3 = 143=42;

(VOID **)&RISER_PCIE_REPORT_TABLE

Status = MbaBiosProtocol->PCIeSlotTableInitTianChi( (VOID **)&RISER_PCIE_REPORT_TABLE, &TableSize );

DEVICE_REPORT_SLOT_INFO RISER_PCIE_REPORT_TABLE_R1_3X8[] = {
    //r1-l
    {SLOT1, CPU0, FALSE, {04,00,01,00}},
    {SLOT2, CPU0, FALSE, {01,00,01,00}},
    {SLOT3, CPU0, FALSE, {01,00,03,00}}
};

DEVICE_REPORT_SLOT_INFO RISER_PCIE_REPORT_TABLE_R1_X16_X8[] = {
    //rl-r
    {SLOT2, CPU0, FALSE, {01,00,01,00}},
    {SLOT3, CPU0, FALSE, {04,00,01,00}}
};   
 

pSlotTable 存储的是DEVICE_REPORT_SLOT_INFO结构体的地址,增加结构体里的值组成表格
请添加图片描述
  如图所示,DEVICE_REPORT_SLOT_INFO结构体字段有7个8bit字段,4个bit为一位,有14位数据,每个结构体在内存空间里有序排列,假设第一个结构体的首地址为0000h,第二个结构体的首地址则为0000014h,第三个结构体数据的首地址为0000028H,当前可记为
p,但是p->next 并不能找到下一个首地址。把地址值变量再存到一个指针里去,假设第一个双指针地址为000030h,第二个为000031h,第三个为32h.记为(VOID **P).
  取结构体值的时候,先取双指针的地址,*p,拿到000000H、000014H,再对结构体进行取值。(VOID **P) = DEVICE_REPORT_SLOT_INFO *p;p->SlotNumber,p->CpuId,获取值

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值