stddef.h下的offset计算结构体属性相对结构体首地址偏移量
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stddef.h>//offsetof函数所在头文件
struct Teacher {
char a;
int b;
};
void test0201() {
struct Teacher t1;
struct Teacher* p = &t1;
//手动计算偏移量:结构体中元素b的实际地址减去结构体首地址即为该元素的地址偏移量
printf("b的属性偏移量:%d\n", (int)&(p->b)-(int)p);
//函数计算偏移量
printf("b的属性偏移量:%d\n", offsetof(struct Teacher, b));
}
通过偏移量访问结构体元素
//单层结构体
void test0202() {
struct Teacher t1 = {'a',10};
//首地址+偏移量得到元素首地址,强转为元素对应指针类型后,按类型读取相应字节数量的数据
printf("t1.b=%d\n", *(int*)((char*)&t1 + offsetof(struct Teacher, b)));
printf("t1.b=%d\n", *(int*)((int*)&t1 + 1));
}
struct Teacher2 {
char a;
int b;
struct Teacher c;
};
//嵌套结构体
void test0203() {
struct Teacher2 t1 = { 'a',10,'b',20};
int offset1 = offsetof(struct Teacher2, c);
int offset2 = offsetof(struct Teacher, b);
printf("%d\n", *(int*)((char*)&t1 + offset1+offset2));
printf("%d\n", ((struct Teacher*)((char*)&t1 + offset1))->b);
}
内存对齐
- cpu按块读取内存,一块是2的n次方字节,内存对齐保证了每个块中的数据是完整的。如果不做内存对齐,可能会出现一个数据跨越两个块,cpu需要做二次访问才能读取完整数据。
- 内存对齐计算
对齐模数默认为8
i.当对齐模数为8时,下述结构体第一个元素a从0开始存储,存4个字节(即存0~3)
ii.第二个元素可以从4开始存储,第二个元素b的大小为1个字节,1比8小,4是1的倍数,所以b从4开始存储,存1个字节(即存4)
iii.第三个元素可以从5开始存储,第三个元素c的大小为8个字节,8与对齐模数相等,该元素要从8的倍数开始存储,5不是8的倍数,所以要从8开始存储,存8个字节(即存8~15)
iV.第四个元素可以从16开始存储,第四个元素d的大小为4个字节,4比8小,16是4的倍数,所以d从16开始存储,存4个字节(即存16~19)
v.四个元素共存20字节,该结构体最大类型为c,大小为8字节,8与对齐模数相等,那么整个结构体存储的空间要为8的倍数,所以整个结构体实际存储24字节。对齐模数修改为1
i.下述结构体第一个元素a从0开始存储,存4个字节(即存0~3)
ii.第二个元素可以从4开始存储,第二个元素b的大小为1个字节,1与对齐模式相等,4是1的倍数,所以b从4开始存储,存1个字节(即存4)
iii.第三个元素可以从5开始存储,第三个元素c的大小为8个字节,8比1大,该元素要从1的倍数开始存储,5是1的倍数,所以可以从5开始存储,存8个字节(即存5~12)
iV.第四个元素可以从13开始存储,第四个元素d的大小为4个字节,4比1大,13是1的倍数,所以d从13开始存储,存4个字节(即存13~16)
v.四个元素共存17字节,该结构体最大类型为c,大小为8字节,8比1大,那么整个结构体存储的空间要为1的倍数,所以整个结构体实际存储17字节。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(show)//查看当前对齐模数,对齐模数可以修改,一般修改为2的n次方
//#pragma pack(1)//修改对齐模数为1
//
//第一个属性开始,从0开始偏移
//第二个属性开始,要放在该类型的大小与对齐模数比取小的值的整数倍
//所有属性都计算完后,再整体做二次偏移,将整体计算结果要放在结构体最大类型与对齐模数比取小的值的整数倍上
typedef struct _STUDENT {
int a;//8-11
char b;//12
double c;//16-23
float d;//23-26
} Student;
//结构体嵌套结构体时,子结构体放在该结构体中最大类型和对齐模数比的整数倍上
typedef struct _STUDENT2 {
char a;//0-7
Student b;//8-31
double c;//32-39
} Student2;
void test0301() {
printf("%d\n", sizeof(Student2));
}
int main(void)
{
test0301();
return 0;
}
版权声明:本文为original_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。