计算结构体与联合体的大小(嵌套)
在C语言中,结构体和联合体是两种非常常见的数据类型,用于定义一组相关的数据,可以使得程序更加灵活。在对结构体和联合体进行实际应用时,往往需要精确地计算其大小,以便正确地申请内存和使用这些数据。本篇博客将详细介绍如何计算结构体和联合体的大小,以及如何计算结构体和联合体的嵌套大小。
非常详细,相信一定可以帮助到你!
一、数据类型大小(64位)
类型 | 大小 |
---|---|
char | 1个字节 |
char*(即指针变量) | 8个字节 |
int | 4个字节 |
unsigned int | 4个字节 |
short int | 2个字节 |
float | 4个字节 |
double | 8个字节 |
long | 8个字节 |
long long | 8个字节 |
unsigned long | 8个字节 |
二、结构体大小
默认对齐方式遵循:与数据类型的字节数最小公倍数对齐。
内存按结构体成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整数倍,如果不够则补齐,依次向后类推。
总之,结构体大小是结构体最宽基本类型成员大小的整数倍。话不多说,上代码。
demo 1
#include <stdio.h>
typedef struct
{
char a[5];
int b;
double c;
}Test;
int main(void)
{
printf("sizeof(Test) = %ld\n",sizeof(Test));
return 0;
}
其中,最大类型字节数8字节。char a[5]占5字节,补齐到8字节,int b占4字节,8+4=12字节,补齐到16字节,double c占8字节。所以:16+8=24字节
编译运行:
demo 2
下面介绍一个结构体大小需要注意的点,可以应用到实现柔性数组,这里就不再展开。
#include<stdio.h>
typedef struct{
int num;
char name[20];
int arr[];
}text1;
typedef struct{
int num;
char name[20];
}text2;
int main() {
printf("结构体text1的大小为:%ld\n", sizeof(text1));
printf("结构体text2的大小为:%ld\n", sizeof(text2));
return 0;
}
编译运行:
从结果可以看出,第一个结构体比第二个结构体多了一个参数 int arr[],但最后的结果确实两个结构体的大小相同。可以说明,在计算结构体时,如果结构体中存在未给定长度的数组,那么在计算时,将会忽略这个数组。
二、联合体大小
联合体又称为共用体,顾名思义所有数据类型共用一块内存。
总之,所占内存的大小必须为最大类型所占字节的最小倍数。话不多说,上代码。
demo
#include<stdio.h>
union
{
char a[7];
int b[2];
double c;
}Test;
int main()
{
printf("sizeof(Test) = %ld\n",sizeof(Test));
return 0;
}
其中,char a[7] 占7字节,int b[2] 占 4*2=8 字节,满足最大类型字节数8字节不需要补齐,double c占8字节。综上最大为8字节。所以,大小为 8字节.
如果将上述代码中,成员b的元素改为3,则:
最大字节类型为double占8字节。char a[7]占7字节,补齐到8字节。int b[3]占12字节,补齐到16字节。综上,最大为16字节。所以,联合体的大小为 16字节。
编译运行:
三、结构体与联合体嵌套
较复杂的是结构体中嵌套联合体。
默认规则:联合体按照最大成员所占字节且为最大数据类型所对应的字节的最小整数倍的原则进行计算,它所占的字节数与结构体中其他成员所占字节的总和应为结构体中最大数据类型所对应的字节的最小倍数。
总之,先计算最里面的联合体,然后正常方法计算结构体其他成员所占字节。最后要对齐的是结构体中的最大字节类型。话不多说,上代码。
demo 1
#include<stdio.h>
typedef struct
{
union
{
char a[10];
int b[2];
double c;
}test;
char d[5];
int e;
double f;
}Test;
int main()
{
printf("sizeof(Test) = %ld\n",sizeof(Test));
return 0;
}
先计算联合体中,最大char a[10]占10字节,但又要为8的最小倍数,因此联合体占16字节。
然后结构体中其余5+4+8=17 字节,不是结构体中最大数据类型 double 所对应的字节数 8的最小倍数,补齐到24字节。
所以,综合起来整个结构体大小:16(联合体所占字节)+ 24字节=40字节
编译运行:
demo 2
由于结构体与联合体大小的计算是找工作时笔试和面试的高频考点,这里分享一道某公司的c语言笔试题。
#include<stdio.h>
typedef union
{
long i;
int k[5];
char c;
}DATE;
typedef struct
{
int cat;
DATE cow;
double dog;
}data;
DATE max;
int main()
{
printf("result:%ld\n",sizeof(data) + sizeof(max));
}
先计算联合体大小:最大int k[5]占20字节,补齐到24字节。所以一个DATE为24字节。
然后计算结构体其余成员大小:4+4+8=16字节
然后计算结构体真正大小:24+16 = 40字节
最后sizeof(data) + sizeof(max):40 + 24 = 64字节
四、指定字节对齐
当我们需要指定字节对齐的时候,需要定义 #pragma pack(value), 这种指定 value 字节进行对齐。直接用代码演示会更容易理解。
demo 1
结构体对齐规则:整体的大小必须为 value 的最小整数倍。
#include<stdio.h>
#pragma pack(4)
typedef struct
{
char a[5];
int b;
double c;
}Test;
int main()
{
printf("sizeof(Test) = %ld\n",sizeof(Test));
return 0;
}
其中,这里以 4字节对齐计算,则成员char a[5] 占5字节,补齐到8字节。
int b占4字节,double c占8字节,均为4的倍数,不用补齐。所以:整体大小为8+4+8=20字节。
编译运行:
demo 2
联合体对齐规则:联合体中最大成员所占字节且必须为value的最小倍数。
#include<stdio.h>
#pragma pack(2)
union
{
char a[7];
int b[3];
double c;
}Test;
int main(void)
{
printf("sizeof(Test) = %ld\n",sizeof(Test));
return 0;
}
指定对齐2字节,char a[7]占7字节,补齐为2的最小倍数8字节。int b[3]占12字节,不用补齐。double c为8字节,不用补齐。所以,最大为12字节。
编译运行:
五、总结
看到这里,相信大家对计算结构体与联合体(嵌套)的大小已经非常清楚了,只要注意与最大字节的数据类型对齐就行。如有不足,欢迎大家评论区讨论。
如果觉得有用的话,就点赞收藏吧。