C语言---自定义类型:结构体(1)https://developer.aliyun.com/article/1544448
结构体对其的规则:
1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他的成员变量要对齐到某个数字(对齐数)的整数倍的地址处
对齐数=编译器默认的一个对齐数与该成员变量大小的较小值
--vs中,默认对其的值是8
--Linux中qcc没有默认对齐数,对齐数就是成员自身的大小
3.结构体总大小为最大对齐数。(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)整数倍
4.如果嵌套了结构体的情况。嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍
//那么结构体是如何对齐的呢? //结构体成员在内存中到底是怎么存放对齐的? //那么我们就了解一下结构体对其的规则 //struct S1 //{ // char c1; // char c2; // int n; //}; // //int main() //{ // struct S1 s1; // // return 0; //} //1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处 /* 2.对齐数=编译器默认的一个对齐数与该成员变量大小的较小值 --vs中,默认对其的值是8 */ //在这个代码中,c1就是第一个成员,占一个字节,那么c1就占了内存中第0行的空间位置 //c2是1个字节,小于vs规定的对齐数8,所以c2要对齐在1的倍数的位置 //那么刚好1是1的倍数,那么c2就占了第1行的空间位置 //因为除了第一个成员,剩下的都是其他成员 //因为n的大小是4个字节,vs默认对齐数是8,4<8,那么c2的对齐数就是4 //所以n此时此刻要对齐在4的倍数上面,就是偏移量是4的倍数就行了 //所以我们是从第4行开始占的,占4个字节 //中间的2 3行是被空着的,因为这两个字节我们用不上了 /* 现在我们将所有成员都放进内存去了,占了8个字节 但是结构体的大小还不能因此判断 我们还要根据第三条进行判断 3.结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数, 所有对齐数中最大的)的整数倍 这三个成员的默对齐数是最大对齐数是4, 那么在这里结构体的大小就是4的倍数,因为这里刚好8是4的倍数,所以我们直接进行判断结构体的大小是8个字节 */ //对s2进行讲解 struct S2 { char c1; int n; char c2; }; int main() { struct S2 s2; return 0; } /* 根据规则 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处 因为c1占一个字节,那么c1就放在第一行的位置 对于n,n的大小是4个字节,vs上默认对齐数是8,因为4<8 那么取这两个数的较小数就是4作为n的对齐数,所以n要对齐4的倍数 那么我们就只能从第四行开始,因为是4个字节大小,所以从第4行到第7行都是n的范围 在这里我们又发现中间的1 2 3行是空的,说明我们又浪费三个字节 对于c2,因为c2的字节大小是1,vs默认对齐数是8,1<8,所以c2的对齐数是1 所以c2找到1的倍数就行了 刚好第8行是1的倍数,那么c2就将第8行占了 到目前为止S2占了9个字节了 但是真的是9个字节吗? 我们还得根据后面的规则进行判断 在S2中,最大的对齐数是4,那么结构体的总大小是4的倍数 但是9 10 11行都不是4的倍数,所以我们只能取第12行, 所以我们中间又浪费了3个字节的大小 所以最终S2结构体的大小是12 */
struct S3 { double d;//0-7 char c;//8 int i;//10-12 //最大对齐数是8,那么最后的位置固定在8的倍数上面,就是16 }; int main() { printf("%d\n", sizeof(struct S3));//16 return 0; } //因为double类型是8个字节,根据结构体对其的规则,构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处 //那么0-就是d占了 /* 对于c来说,c大小1个字节,vs默认对齐数是8,因为1<8,所以c的对齐数是1 那么只要是1的倍数就行了 所以c就将第8行占了 对于i,i是4个字节,vs默认对齐数是8,4<8所以i的对齐数是4的倍数 所以 9 10 11这三块字节浪费了,直接从12开始,因为是4个字节大小,所以i的空间就是12-15行 因为这三个数据的最大对齐数是8,所以最后的结构体的大小要取8的倍数,,那么我们只能取16了 所以最后这个结构体大小就是16 */
//练习4-结构体嵌套问题 struct S3 { double d; char c; int i; }; struct S4 { char c1; struct S3 s3; double d; }; int main() { struct S4 s4; printf("%d\n", sizeof(struct S4));//32 return 0; } /* 这种就是结构体嵌套了一种其他类型的结构体变量 我们在之前就将S3的大小算出来了,是16个字节的大小 S4成员c1因为是第一个成员,肯定是放在偏移量为0的地址处 因为c1类型是char类型,一个字节大小,所以第0行被c1占了 c1放完我们放s3 因为我们计算出的s3是16个字节,但是这个16个字节从哪里开始放呢? 根据规则4 如果嵌套了结构体的情况。嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处, 结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍 所以s3要对齐到字节的结构体内最大对齐数8的整数倍处 所以s3对齐到8的倍数就行了,因为第一个8的倍数是8 所以s3是从第8行开始对齐的,因为大小是16个字节 所以s3占了8-23行 所以中间的1-7行的7个字节被浪费了 对于d来说,因为类型是double,大小是8个字节,vs默认对齐数是8, 那么d的对齐数是8,所以d要对齐8的倍数位 因为24是8的对齐数,所以d从24行开始对齐,d的大小是8个字节 所以24-31行是d占了 现在我们已经占了32个字节了,从0-31行 那么32是不是我们最终的大小呢? 在规则4中我们还说到 结构体的整数大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍 因为这哥结构体所有成员中对齐数里面最大对齐数是8 并且我们结构的大小最终还是要取决最大对齐数的倍数, 因为最大对齐数的倍数是8 所以最终这个结构体的大小我们取32 */
C语言---自定义类型:结构体(3)https://developer.aliyun.com/article/1544453