结构体和联合体的一些问题
作者:互联网
查漏补缺一些结构体问题
结构体在内存中的对齐规则
- 结构体变量的首地址,必须是结构体变量中最大基本数据类型成员所占字节数的整数倍。
- 结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
- 结构体变量的总大小,为结构体变量中最大基本数据类型成员所占字节数的整数倍。
不好理解,用例子来看
示例
示例1
struct node
{
char a;
int b;
double c;
};
int main(void)
{
struct node S1;
printf("size of S1 is %d\n", sizeof(S1));
return 0;
}
结果:
原因:
结构体中的成员是按照定义顺序一个一个放入内存的,但并不是紧密排列。
从结构体存储的首地址开始,每个元素放置到内存中时,都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己的所占字节数的整数倍上开始。
就上个例子来说,当系统为a开辟空间后,再存放整型变量b时,会以四个字节为单位进行存储,但第一个四字节块已经被a占了,所以b会存到下一个四字节块中,同理double类型的变量c会以八字节进行存储,第一个八字节块有数据,就找下一八字节块。
示例二
struct node
{
char a;
double b;
int c;
};
该变一下b和c的类型,我这里相当于把double类型放到第二个位置
运行结果:
这说明了规则的第三条:
结构体变量的总大小,为结构体变量中最大基本数据类型成员所占字节数的整数倍。
当为最后一个int类型变量开辟空间后,发现总大小不是最大类型double所占字节数的整数倍,那就要补齐。
图示:
为什么要理解字节对齐问题
总结:
- 内存大小的基本单位是字节,但cpu并不是逐字节读写内存,而是以2,4或8的倍数的字节块来读写内存。因此,就会对基本数据类型的地址做出一些限制,即它的地址必须是2,4或8的倍数,要求他们按照这个规则排列,这就是对齐。
- 有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit 数据。显然在读取效率上下降很多。
- 不同的平台对齐方式可能不同,这就导致同样的结构在不同的平台大小可能不一样,互相发送的数据可能出现错乱。
结构体和联合体的区别
联合体和结构体有相同之处,但两者有本质的不同。
结构体中,各成员有各自的内存空间;
而联合体的成员共用一块内存,这块内存的大小是各成员中最大类型所占的字节大小。
这里说的共享不是指把多个成员同时装入一个联合体变量内,而是指该联合变量可被赋予任一成员值,每次只能赋一种值,赋入新值会冲去旧值。
示例:
struct node
{
char a;
int b;
double c;
};
union node2
{
char a;
int b;
double c;
};
int main(void)
{
struct node S1;
union node2 S2;
printf("size of S1 is %d\n", sizeof(S1));
printf("sizeof S2 is %d\n", sizeof(S2));
return 0;
}
标签:字节,int,double,联合体,内存,一些,变量,结构 来源: https://blog.csdn.net/m0_56257585/article/details/120584476