结构体的对齐与偏移量的计算

本文详细介绍了结构体的字节对齐规则,包括结构体变量的首地址对齐、成员相对偏移量以及总大小的对齐原则。字节对齐是为了提高内存访问效率,避免因地址不匹配带来的额外读取操作。通过预编译指令如`#pragma pack`可以调整对齐方式,以节省空间。同时,文章提供了计算结构体成员偏移量的方法,并探讨了如何判断数据的存储方式是大端还是小端。两种判断方法分别利用字符指针和联合体进行验证。
摘要由CSDN通过智能技术生成

对齐规则(三条)

  1. 结构体变量的首地址,必须是结构体变量中“最大基本数据类型成员所占字节数”的整数倍。
  2. 结构体变量中每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
  3. 结构体变量的总大小,为结构变量中“最大基本数据类型成员所占字节数”的整数倍。
struct node{
	char cha;
	int ia;
	char chb;
};
sizeof(struct node ) = 12 //字节

为什么需要字节对齐

  1. 字节是内存的基本单位,理论上可以访问任意变量,但是,实际上cup并非逐字节的读取内存,而是以2,4,8,的倍数的字节来读取内存。因此,就会对数据类型的地址做出一些限制,即他的地址必须是2,4,8的整数倍。这就要求,各种数据类型在内存上按一定的规则排列,也就是对齐;
  2. 有的平台每次读地址都是从偶地址开始,如果存放变量在奇地址开始的地方,那么一个地址可能要读两次,然后进行拼凑,效率较低。
  3. 不同平台的对齐方式可能不同,如此一来,同样的结构在不同的平台其大小可能不同,二者之间发送的数据可能出现错乱。

指令对齐

/#pragma pack(1)

struct node{
	char cha;
	int ia;
	char chb;
};
sizeof(struct node) = 6

在设计结构体时,我们既要满足对齐又要节省空间,如何做?

结构体成员按成员大小依次升序排列;

不定义结构体变量,如何计算结构体成员的相对偏移量?

无中生有:vs环境下可以运行;

#include<iostream>
using namespace std;
struct  node
{
	char ch1;
	int i;
	char ch2;

};
int main() {
	node* p = NULL;
	cout << (int)(&(p)->i) << endl;
	return 0;
}

如何判断是大端存放,还是小段存放?

大端存储与小端存储区别如下:

小端存储:数据的高位数据放在高地址,低位数据放在低地址。

大端存储:大端与小端的数据存储方式相反。数据的高位数据放在低地址,低位数据放在高地址。

对于大小端存储判断的方式有两种:

方法一:字符指针判断

在32位平台下,int占4个字节,而char类型的指针是占一个字节的,如果我们把int强传为char类型的指针,只会保存一个字节的数据,那么我们只需要判断char里面的第一个字节和int里面的第一个字节是否是一致即可判断。
如果一致则为小端模式,反之为大端模式。

注:
下面代码我们令 int a=1 如果是小端模式,int下1会存放在在低地址处,而强传为char类型的指针,1也在低地址处,所以可以判断。

#include <stdio.h>
int main()
{
    int a = 1;
    if (*(char*)&a == 1)
        printf( "小端模式" );
    else
       printf( "大端模式" );
    return 0;
}

方法二:联合体判断

由于联合体所有数据共享一块地址空间,存放数据的所有成员都是从低地址开始存放,所以我们可以在联合体内定义一个int和一个char类型变量,然后在外部实例化的时候创建int变量,用char变量调用,相当于隐式类型转化,如果结果为1,则低字节存放在低地址,既是小端机器,反之大端机器。

#include <stdio.h>
union Test
{
    int a;
    char b;
};
int main()
{
    Test t;
    t.a = 1;
    if (t.b == 1)
        printf( "小端模式" );
    else
        printf( "大端模式" );
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jie3606

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值