结构体对齐规则及位域规则

让我们看看下面两个代码:

struct S1
{
	char c1;//1
	int i;//4
	char c2;//1
};

struct S2
{
	char c1;//1
	char c2;//1
	int i;//4

};
int main()
{
	struct S1 s1 = { 0 };
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(s1));
	printf("%d\n", sizeof(struct S2));
	system("pause");
	return 0;
}

得出的结果会不会是一样的呢?
让我们看下结果:
在这里插入图片描述
答案是否定的。

造成这样的原因是:结构体对齐

结构体对齐的规则:

  • 1.第一个成员在与结构体偏移量为0的地质处
  • 2.其他成员变量要对其到某个数字(对其数)的整数倍的地址处
    对齐数=编译器默认的一个对齐数与该成员大小的较小值(vs下为8, linux下为4)(#pragma (4、8) 可以用来控制默认对齐数的大小)
  • 3.结构体总大小为最大对齐数(每个成员都有一个对齐数)的整数倍
  • 4.如果出现嵌套情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

对齐规则如下图:共占12个字节
结构体对齐规则及位域规则_第1张图片

关于3 和 4规则 的运用:

struct S3
{
	double d;//0- 7
	char c;//8
	//8-11被占用
	int i;//12-15
};//16

struct S4
{
	char c1;//0
	//占用0-7
	struct S3 s3;
	//占用8 - 23
	double d;//23 - 31

};//总计32
	printf("%d\n", sizeof(struct S3));
	printf("%d\n", sizeof(struct S4));
	printf("%d\n", offsetof(struct S4, c1));
	printf("%d\n", offsetof(struct S4, s3));
	printf("%d\n", offsetof(struct S4, d));

结果
结构体对齐规则及位域规则_第2张图片

为什么存在对其?

1.平台原理(移植问题):不是所有硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出异常
2.性能问题:数据结构应该尽可能的在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要两次内存访问,而对齐的只需要一次。

位域:

位域 :必须有“int”、“signed int”或“unsigned int”类型但是很多编译器都对类型有拓展。
规则:
-1.如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof的大小,则后面的字符将紧邻前一个字段存储,直到不能容纳为止。

  • 2.如果相邻位域的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍。
  • 3.如果相邻的位域字段的类型不同,不同的编译器具体实现有差异,VC6采取不压缩的方法,Dev-c++,gcc的压缩方式
  • 4.如果位域字段之间穿插着非位域字段,则不压缩。
  • 5.整个结构体的大小为最宽基本类型成员大小的整数倍。

例子:

struct A
{
	char    a : 2;
	char    b : 3;
	char    c : 1;
};

struct B
{
	char    a : 2;
	char    b : 3;
	char    c : 7;
};

struct C
{ 
	unsigned a : 19;
	unsigned b : 11;
	unsigned c : 4;
	unsigned d : 29;
	char index;
};

struct D 
{
	char    a : 2;
	char    b : 8;
	int		c : 1;
};

struct E
{
	int i : 8;
	int j : 4;
	double b;
	int a : 3;
};

struct F
{
	int i : 8;
	int j : 4;
	char b : 1;
	int a : 3;
};

int main()
{
	printf("%d\n", sizeof(A));
	printf("%d\n", sizeof(B));
	printf("%d\n", sizeof(C));
	printf("%d\n", sizeof(D));
	printf("%d\n", sizeof(E));
	printf("%d\n", sizeof(F));


	system("pause");
}

结构体对齐规则及位域规则_第3张图片

你可能感兴趣的:(C,面试题总结)