【C语言】结构体内存对齐

(一)结构体的概念:

什么是结构体?

结构体是由一批数据组合而成的一种新的数据类型。组成结构型数据的每个数据称为结构型数据的“成员”。

为什么需要结构体?

C语言中有许多内置类型比如:整形(int,long,char等),浮点型(flaot,double),还有数组,指针,字符串等。但是在实际问题中只有这些数据类型是不够的,比如一个学生的信息就需要学号(字符串),姓名(字符串),年龄(整形)等等,如果零散的定义多个不同类型的变量,来描述一个学生的话使用起来就会很乱。所以我们就需要一个新的数据类型。——结构体,他就将不同类型的数据存放在一起,作为一个整体进行处理。

(二)结构体内存对齐:

(1)什么是结构体内存对齐?

内存地址对齐,是结构体在内存中排列数据(表现为变量的地址)、访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:结构体成员对齐和结构体整体对齐 。
结构体成员对齐:
对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min( 默认对齐数,这个数据成员的自身长度 ) 的整数倍。
结构体整体对齐:
在结构体数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,结构体最终的大小是 min(默认对齐数,最大的结构体成员类型长度) 的整数倍。
默认对齐数和编译器有关,VS的默认对齐数 是 8.
举例说明:

struct S1
{
 char c1;
 int i;
 char c2;
};

S1结构体的大小计算: (环境:vs win32默认对齐数 是8)
(1)每个成员对齐:c1是第一个成员,假设地址是x,c1的大小是1个字节。如果不考虑内存对齐,下一个成员从x + 1开始存储。第二个成员i 的大小是 4字节,默认对齐数是8字节, min(sizeof(i) = 4,默认对齐数) = 4。所以i从x + 4的地址开始存储直到 x + 7。第三个成员 c2,min(sizeof(c2), 4) = 1;所以直接存到 x + 8的位置。
(2)结构体整体对齐:经过结构体成员对齐后, 结构体的大小是(地址x ~ 地址x + 8)的内存块 = 9字节;min(8, 最大数据类型成员的大小 = 4); 9 不是 4的整数倍 所以补三个字节。最终结构体的大小是12。

(2)为什么需要结构对齐?

(1)为了平台的可移植性,不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
(2)为了性能:在我们看来,内存的是一个字节一个字节组成的,但是CPU对内存的存取操作是以块为最小单位的。快的大小可以是2,4,8。也就是2的整数次幂。假如块的大小是4. 我们看下面的结构体。
struct S2{
char c;
int a;
}
将a变量取到寄存器中对应的操作:
如果不考虑内存对齐的话,设c的地址是 0。a变量占的地址空间是1234.而CPU要取出 a的值,需要两次访问内存,分别将第一块 (0123) 和第二块 (4567)的数据都取出来。然后将(1234)合并得到a的值。
如果考虑内存对齐的话,a对应的内存空间是(4567),cpu只需要访问一次内存空间,便可直接取出a的值。这样做,虽然浪费了3个字节的空间,但是提高了效率。所以 内存对齐就是一种用空间换时间的过程。

(3)求结构体成员相对于起始位置的偏移量。

求结构体某成员相对起始位置的偏移量,可以用 offsetof(TYPE, MEMBER) 宏来实现。
例如:

struct S1
{
	char c1;
	char c2;
	double i;
};
int main(){
	cout << offsetof(struct S1, i) << endl;
	return 0;
}

上边的代码输出结果是8.
offsetof(TYPE, MEMBER)是如何实现的?
#define offsetof(TYPE, MEMBER) (size_t)& ( (TYPE*) 0)->MEMBER

这段代码的含义是将,内存从零开始的一段数据 当做struct S1来处理。相应的找到MEMBER成员的位置。也就是他的偏移量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值