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

对齐规则(三条)

  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;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: C语言标准中关于结构体对齐的定义,可以用以下中文来解释: 结构体成员的对齐方式是指,为了使结构体的访问效率最高,编译器将结构体成员按照特定规则分配到内存中的位置。在分配时,编译器会将结构体成员的大小和相对位置考虑在内,以保证成员的对齐。这样可以避免在访问结构体成员时出现性能上的问题。 具体来说,C语言标准规定了以下几个对齐原则: 1. 结构体的首地址必须是其最宽基本类型成员的首地址; 2. 每个成员相对于结构体首地址的偏移量必须是该成员大小的整数倍; 3. 结构体的总大小必须是最宽基本类型成员大小的整数倍。 根据这些原则,编译器会在结构体成员之间插入填充字节,以保证成员的对齐。这样可以提高CPU读取内存的效率,减少内存访问次数和数据传输量,从而提高程序的性能。 ### 回答2: C语言标准中关于结构体对齐的定义主要包含以下几点。 首先,结构体对齐是为了保证结构体的成员在内存中的存储位置符合一定的规则,以提高计算机的访问效率。 其次,对于一个结构体变量,其起始地址必须是所有基本类型成员中的首字节地址,而非基本类型成员的起始地址可以是任意的。 接着,结构体对齐要求由编译器根据具体实现来决定,可能受到硬件和操作系统的限制。 另外,编译器通常会在结构体的成员之间添加填充字节,以满足对齐要求。填充字节的数量取决于结构体成员的类型和前一个成员结束地址与对齐边界的差值。 最后,使用特定的编译指示(如#pragma pack(n))可以改变默认的对齐方式。这样做可能会降低对齐的效果,但可以满足某些特殊需求。 总结来说,C语言标准中关于结构体对齐的定义规定了结构体成员在内存中的存储方式。对齐规则由编译器根据实际情况来决定,并可通过编译指示进行修改。结构体对齐的目的在于提高计算机的访问效率,确保结构体成员存储位置的正确性。 ### 回答3: C语言标准中关于结构体对齐的定义主要有两个方面,分别是默认对齐方式和自定义对齐方式。 首先是默认对齐方式,默认情况下,结构体对齐方式要求结构体的每个成员的地址都能够被结构体中最宽基本类型的大小整除,也就是说,结构体对齐大小必须是其成员中最宽数据类型的大小或其整数倍。如果结构体中的成员包含指针类型或者更宽的基本类型,那么该结构体的大小会被这些类型的大小所影响。 其次是自定义对齐方式,在C语言标准中,可以通过在结构体定义前使用特定的编译器指令(如`#pragma pack`)来自定义结构体对齐方式。通过设置对齐方式,可以控制结构体成员的对齐间距。例如,可以使用`#pragma pack(n)`来指定结构体对齐方式为n字节。这种自定义对齐方式可以用于优化内存布局,减小内存开销。 总的来说,C语言标准对结构体对齐的定义要求保证结构体的成员能够按照其类型在内存中正确对齐,同时允许使用自定义对齐方式以满足特定需求。对结构体对齐的规定有助于确保内存的有效利用和提高程序执行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jie3606

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

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

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

打赏作者

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

抵扣说明:

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

余额充值