零基础入门之结构体字节对齐

一、字节对齐的规则:

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

posted @ 2019-11-13 14:28  国产零零柒  阅读(1013)  评论(0编辑  收藏  举报