一、字节对齐的规则:
1、一般设置的对齐方式为1,2,4字节对齐方式。结构的首地址必须是结构内最宽类型的整数倍地址;另外,结构体的每一个成员起始地址必须是自身类型大小的整数倍(需要特别注意的是windows下是这样的,但在linux的gcc编译器下最高为4字节对齐),否则在前一类型后补0;这里特别提到的是数组一定要注意,而且在一些编程的技巧中,我们可以使用数组强制字节达到对齐的目的。这在网络编程中是很常见的。
举例:比如CHAR型占用空间为1字节,则其起始位置必须可被1整除。INT为4字节,其起始位置必须被4带队,依次类推。(我们假定类或结构体的起始位置为0位置,其实编译器是在开辟空间时,会寻找起始位置可被结构内最宽类型整除的地址做为开始地址,因此我们可以假定其为0值,因为这0值可以被任意的类型整除。)
2、结构体的整体大小必须可被对齐值整除,默认4(结构中的类型大小都小于默认的4)。
3、结构体的整体大小必须可被本结构内的最宽类型整除。(其实和上一条是一样的,但这里独立出来,起注意作用。比如结构体里的有DOUBLE,那么结构的大小最后必须可被8整除)
注意:GCC不是这样,就是最高只能被4整除。此为32位系统,64为系统也会采用8整除的方式。否则(2、3条),编译器会在结构的最后添充一定的特定字符来补齐。
struct T { char ch; double d ; };
此结果强调为32系统在VC中是16个字节,GCC中为12个字节。64位依旧是16个字节
4、对于结构体内嵌套结构体的形势,规定是必须按照基本数据类型来定义,而不能以嵌套结构大小来做为上三种使用的基准。(总结)结构体可以处理成char类型。
二、举例:
struct A { int a; char b; short c; }; //8 struct B { char b; int a; short c; }; // 12 struct C { double t; char b; int a; short c; }; //24 struct D { char b; double t; int a; short c; };//24
在VC中,SIZEOF这四个结构体,分别为:8、12、24、24;
我们先谈第一个,(说明一下,在考虑结构体大小时,我们基本可以忽略起始地址的问题,因为这个编
译器会自动为我们做好,见上面的说明),结构体内首先是一个INT的4字节,起始地址假定为0,整除4,其小于等于默认的4字节对齐且0为4(INT的占用空间)的整数倍,所以,其占四个字节;其后为起始地址为5,空间为1个字节的CHAR,小于4且5为1(CHAR占用空间)的整数倍,故占用1个字节,然后是一个起始地址为5占2个字节的SHORT,其小于4,但5不为2位数,故补齐一个字节,从第6个字节开始,占2字节空间。所以共占用4+1+1(补)+2=8;8/4=2;整除,故占用8字节空间。
再谈第2个,CHAR不用解释,占有一个字节空间,且可以被0地址整除。而INT则占4字节空间,所以其必须在CHAR后补齐3字节,到第四个字节,才是INT的真正地址。SHORT也不用说,所以共占有:1+3(补)+4+2=10个字节,但10不能整除4,所以要在结构体最后补齐2字节。故实际占有10+2=
12个字节。
谈第三个,C结构体只是在B结构体前加了一个DOUBLE,其它都一样,按说应该是20个字节啊,但注意我们上面规则的第3条。必须是最宽类型的整数倍,一定要分清,所以得补齐到24,D结构体类似,不再讲。
Linux系统32位与64位GCC编译器基本数据类型长度对照表
GCC 32位 sizeof(char) = 1 sizeof(double) = 8 sizeof(float) = 4 sizeof(int) = 4 sizeof(short) = 2 sizeof(long) = 4 sizeof(long long) = 8 sizeof(long double) = 12 sizeof(complex long double) = 24 指针是4字节; |
GCC 64位 sizeof(char) = 1 sizeof(double) = 8 sizeof(float) = 4 sizeof(int) = 4 sizeof(short) = 2 sizeof(long) = 8 sizeof(long long) = 8 sizeof(long double) = 16 sizeof(complex long double) = 32 指针是8字节 |
实例参考:
GNU
C扩展的__attribute__ 机制被用来设置函数、变量、类型的属性,其用得较多的是处理字节对齐的问题。
__attribute__ 的语法为:
__attribute__ ((语法列表))参数aligned(number)
[number为最小对齐的字节数]是用得较多的一个。
另一个是参数packed
表示“使用最小对齐”方式,即对变量是字节对齐,对于域是位对齐。
#include struct A{ char a; //1Byte int b; //4B unsigned short c;//2B long d; //4B unsigned long long e; //8B char f; //1B }; struct B{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned)); struct C{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(1))); struct D{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(4))); struct E{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(8))); struct F{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((packed)); struct H{ char a; double b; }; int main(int argc, char **argv) { struct A a; struct B b; struct C c; struct D d; struct E e; struct F f; printf("A = %d, B = %d, C = %d, D = %d, E = %d, F = %d, H = %d\n", sizeof(struct A), sizeof(struct B), sizeof(struct C), sizeof(struct D), sizeof(struct E), sizeof(struct F),sizeof(struct H)); return 0; }
结果:
$ ./aligned32 A = 28, B = 32, C = 28, D = 28, E = 32, F = 20, H = 12 $ ./aligned64 A = 40, B = 48, C = 40, D = 40, E = 40, F = 24, H = 16
分享一些C语言相关的资料
结构体普及与应用
http://www.makeru.com.cn/live/5413_1909.html?s=45051
C语言玩转链表
http://www.makeru.com.cn/live/1392_338.html?s=45051
必备Linux命令和C语言基础
http://www.makeru.com.cn/video/1862.html?s=45051
释放潜能:学习效率提升、编程能力提升
http://www.makeru.com.cn/live/3507_1276.html?s=45051
原文地址:https://www.cnblogs.com/923327iu/p/11848655.html