结构体对齐
成员偏移的计算方法
成员偏移(member offset):相对于结构体首地址的偏移
结构体对齐支持1 2 4 8 16 项目属性中代码生成可设置
MSVC编译器默认对齐是8 属性 /Zp8
member offset % min(ZpValue,sizeof(member type)) == 0
成员的偏移取模 取默认对齐的值与偏移后的成员的类型大小的最小值
#include<stdio.h>
#include<malloc.h>
typedef struct _Info
{
char szValue[6];
相对于结构体首地址偏移0
float fValue;
相对于结构体首地址偏移8 offset % min(8,4) 相当于 offset % 8 == 0
offset的值为8
不能是4的原因:offset是相对于首地址偏移。char占了6位,所以再占内存从第7位开始占。配合公式取第一个可取的数就是8
此时char所占六个字节但要偏移八个字节,未占的字节被填充
double dbValue;
相对于结构体首地址偏移16 offset % min(8,8) 相当于 offset % 8 == 0
offset的值为16
16的原因:float占内存从地址9(内存开始的地址)+ 4(自己要占内存的大小)= 13(到float占完内存后的新位置),所以offset从13位开始套公式计算,最终结果是16
short sValue;
相对于结构体首地址偏移24 offset % min(8,2) 相当于 offset % 2 == 0
offset的值为24
int nValue;
相对于结构体首地址偏移26 offset % min(8,4) 相当于 offset % 4 == 0
offset的值为28
char cValue;
相对于结构体首地址偏移32 offset % min(8,4) 相当于 offset % 1 == 0
//offset的值为32
}Info,*pInfo;//结构体定义完以后相对于结构体首地址偏移33
int main()
{
Info obj = { "rkvir", 12.5f,100.5,222,0xFFFFFFF,'c' };
上述结构体内存如下
72 6b 76 69 rkvi
72 00 cc cc r\0aa
00 00 48 41 float
cc cc cc cc
00 00 00 00 double
00 20 59 40 double
de 00 cc cc short
ff ff ff ff int
63 char
一共33字节
printf("%d\r\n", sizeof(Info));
sizeof(Info) = 40
变量总和 6 + 4 + 8 + 2 + 4 + 1 = 25
最大对其 * 成员个数 = 48
成员对齐后大小 = 33
对齐支持1 2 4 8 16 项目属性中代码生成可设置
size % 8 == 0 从33开始取
sizeof(Info)== 40
所以最终结构体大小为40
结构体中指针的应用
pInfo pobj;
pobj = &obj;
printf("0x%X\r\n",*(int*)((char*)pobj + 28));
//pobj指向结构体首地址 + 28指向成员
//加的28是指针定义的是什么类型,加的长度就是什么类型的长度
//由于是28个字节的长度,所以要定义成char类型的指针,所以(char*)pobj + 28)。此时他代表着一个地址
//此时要把这个地址取出来,利用int*,将其转换成四字节的数据
//最后取地址*
指针进阶
一维指针在数组的应用
void text(int** p)
{
for (int i = 0; i < 5; i++)
{
printf("%d/r/n",* (*(p + i)));
}
}
int** pArr = (int**)malloc(sizeof(int*) * 5);
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int e = 50;
pArr[0] = &a;
//pArr[0] = int* p; p = &a
pArr[1] = &b;
pArr[2] = &c;
pArr[3] = &d;
pArr[4] = &e;
text(pArr);
二维数组的指针应用
二级指针 指向的每一个空间都是一个一级指针
//一个一维数组:int nArr1[4] = {1,2,3,4};
//int* p
//p = nArr1表示一维数组
//int nArr[3][4] 含义三个一维数组,每个一维数组四个元素
//int(*p)[4],此时int(*p)表示指向一维数组
//p + 1 指向第二个一维数组,不再是加一个sizeof(int)
// 而是加一个sizeof(int) * 4(加了一个一维数组的四个元素类型大小
int nArr[3][4] = { {11,22,33,44},{18,99,48,44},{15,94,36,44} };
int(*p)[4];
p = nArr;
for (int i = 0; i < 3; i++)
{
for (int k = 0; k < 4; k++)
{
//p[一级数组的索引] p[0] = {11,22,33,44},p[1] = {18,99,48,44}
//p[0] = {11,22,33,44},Addr 指针加法 类型步进
//k = 0 1 2 3 一维数组的元素地址
//p[i] + k 地址
//*(p[i] + k)地址上的值
printf("%d\r\n", *(p[i] + k));
printf("%d\r\n",*(*(p + i) + k)
}
}
return 0;
}