参考 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] + 2sizeof(char)4
a[i][j] 的地址 &a[0] + isizeof(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,获取值