关于结构体、联合体、类的大小比较

在学习C语言的过程中,我们经常会遇到求结构体、联合体或者类的大小。除了明确基本元素的大小,还需要考虑内存对齐带来的影响。为了提高计算机的读写速度,采用内存对齐的方式以空间换时间,因此要考虑到在不同的编译环境下,内存字节对齐存在差异。

注:在此篇文章中的基本数据类型均为在32位系统下。

结构体(struct):由一系列具有相同类型或不同类型的数据构成的数据集合。

在实际项目中,结构体和其他类型基础数据类型一样,结构体是大量存在的。结构体的大小不是结构体元素单纯相加就行的,需要考虑到系统在存储结构体变量时的地址对齐问题。对齐方式如下:

1.每个成员的偏移量都必须是当前成员所占内存大小的整数倍,否则在成员之前加上偏移量;

2.当前所以成员大小计算完毕,编译器判断当前结构提的大小是否为结构体中最大基本数据项的整数倍,如不是在最后一个成员后做字节填充。

	struct stuA//5
	{
		char name[4];//4
		char sex;//1
	};
	struct stuB//8
	{
		int num;//4
		char sex;//1
	};

stuA 中 name 为4个字节,偏移量为0,sex 为1个字节,偏移量为0,所有数据项计算结束,当前结构体大小为5,不填充,stuA为5个字节。

stuB 中 num 为4个字节,偏移量为0,sex 为1个字节,偏移量为0,所有数据项计算结束,当前结构体大小为5,整体对齐时在 sex 之后填充3个字节,stuB为8个字节。

stuA,、stuB虽然数据项的大小相同,但是基本数据项stuA 为一个字节的char ,stuB 为四个字节的 int。


在实际的使用过程中还需要注意一下,不被sizeof计算的问题:

struct stuC//4
	{
		int num;//4
		static int sex;//1
	};
sizeof()只计算栈中分配的大小,而sex为静态变量是存放在全局数据区,不计算在内。stuC 中 num 为4个字节,偏移量为0,

当前结构体大小为4,不填充,stuC为4个字节。

联合体(union):也叫共用体,几个不同的变量共同占用一段内存的结构。

联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。
同一时间只能存储1个被选择的变量,对其他成员变量赋值会覆盖原变量。
因此,联合体的大小应为 
1.容纳下最大数据项的大小;
2.能被所有的基本数据类型都能整数。
typedef union U//12
{  
    char arr[9];//9
    int num;//4
}U; 
U 中 arr 为9个 字节大小,num 为4个字节大小,因此 U 的大小为12个字节。

类(class):用户自定义类型,每个类中包含数据说明和操作数据函数。

关于类的内存大小,需要注意:
1.虚函数,编译器需要为类构建虚函数表,类中需要存储一个指针指向虚函数表的首地址;
2.静态成员函数,类的所有实例共享,不被sizeof计算在内;
3.普通函数或静态普通函数,都存储在栈中,不被sizeof计算在内;
class A //12
{
    public:
            virtual void funa();
            virtual void funb();//4
            void func();
            static void fund();
            static int si;
    private:
            int num;//4
            char sex;//1
};

根据内存对齐规则,funa() 和 funb()会构建虚函数表的首地址,4个字节大小,偏移量为0,func()和fund()存储在栈中,不被sizeof()计算,
si 为静态成员函数,所有实例共享不被sizeof()计算,num 为4个字节,偏移量为0,sex为1个字节,偏移量为0,数据项计算结束,当前类的大小为9,
整体对齐时,sex之后填充3个字节,A的大小为12个字节。


参考文献1:C语言结构体大小计算

参考文献2:C语言sizeof求结构体大小问题汇总


发布了26 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Teemo_king/article/details/78242529
今日推荐