一、背景
计算机存储数据时,是以字节(byte = 8bit)为单位进行存储的,其地址不是随意分配的,而是按一定的规律来存储。
为什么要要按一定规律来存储数据呢?随机分配地址,紧密排列数据不香吗?
对于不同硬件平台,其对数据存取的规则存在差异,对于特殊类型的数据需要存储在特殊地址上;对于一些架构CPU需要对存储的数据进行字节对齐,否则会出错,因此会影响数据存取效率。(后期需要大佬辅助补充);
为什么需要结构体字节对齐?
结构体即是一些数据的集合,其首地址就是第一个元素地址,如果没有字节对齐,其各个元素紧密相连,这样理论上是没有问题的;但是如果在32位系统上对这样的数据进行读取时,会出现下面这个问题:
每次机器只能读取4个字节,这样会把中间数据分割开,进行两次读取,无形中会影响读取数据的效率。甚至会出现数据读取错误。
二、结构体字节对齐规则:
1.结构体的总长度(sizeof)为结构体中最宽类型的整数倍;
2.结构体中元素地址到结构体首地址的偏移量为其类型的整数倍;
3.结构体的首地址是结构体中最宽类型的整数倍(我们一般不用考虑,编译器会自动分配);
4.当指定对齐参数 n时,每个类型的大小 与n 比较,以小的值为对齐值,进行字节对齐;
5.当结构体1 中函数结构体2 时,结构体2 首地址按照 结构体2 中最宽类型获取;结构体1 中最宽类型 如果为结构体2,则结构体1的长度应为结构体2宽度的整数倍。
三、结合实例进行验证
typedef struct{ char a; double b; char c;}YCH_TEST1_STRU;typedef struct{ char a; char b; double c;}YCH_TEST2_STRU;sizeof(teest1_stru) : 24test1_stru :0019F2ACtest1_stru.a :0019F2ACtest1_stru.b :0019F2B4test1_stru.c :0019F2BCa------------b------------c-------------|-8----->|-8---->|1 + sizeof(teest2_stru) : 16test2_stru :0019F29Ctest2_stru.a :0019F29Ctest2_stru.b :0019F29Dtest2_stru.c :0019F2A4a--------b-------------c------------|-1--->|1 +
下面给出一个实例,验证结构体嵌套结构体的字节对齐案例:
#include #include // ---------------------------------------------------using namespace std;// ---------------------------------------------------typedef struct { char a; double b; char c;}YCH_TEST1_STRU;// ------------------------typedef struct { char a; YCH_TEST1_STRU b; int c;}YCH_TEST2_STRU;// ---------------------------------------------------// ---------------------------------------------------int main(){ // ---------------------------------------- YCH_TEST1_STRU test1; memset(&test1, 0, sizeof(test1)); YCH_TEST2_STRU test2; memset(&test2, 0, sizeof(test2)); // ---------------------------------------- char str[100] = { 0 }; snprintf(str, 100, "size of test1 : %d", sizeof(test1)); cout << str << endl; snprintf(str, 100, "size of test2 : %d", sizeof(test2)); cout << str << endl; // ---------------------------------------- snprintf(str, 100, "addresss of test2 : %p", &test2); cout << str << endl; snprintf(str, 100, "addresss of test2.a : %p", &test2.a); cout << str << endl; snprintf(str, 100, "addresss of test2.b :%p", &test2.b); cout << str << endl; snprintf(str, 100, "addresss of test2.c : %p", &test2.c); cout << str << endl; // ---------------------------------------- return 0;}// ---------------------------------------------------// ---------------------------------------------------输出:size of test1 : 24size of test2 : 40addresss of test2 : 011AF758addresss of test2.a : 011AF758addresss of test2.b :011AF760addresss of test2.c : 011AF778