对于结构体,联合体,枚举的总结。内存对齐及结构体大小问题,位段问题。

时间:2022-09-05 21:01:00

在c语言中,学习自定义类型,有数组,结构体,联合体,枚举。现在咱们来讨论一下后三者。

结构体原型声明:

struct tag
{
    member-list;
}variable-list;

这样对于大都数没学过结构体的人来说看起来不是很懂。

那么咱们来具体的实例:

struct stu	//stu为结构体名
{
	char name[20];  //成员
	int age;	//成员
};
对于上面也是一个声明,那么怎么来定义结构体变量呢?

struct stu s;

这里的s就是结果构体变量,struct stu 就是类型。

那么怎么通过结构体来访问成员呢?结构体变量加点  例如:s.name   s.age;

如果是结构体指针也可以通过->或者*p.  的方法来访问成员。

对于结构体初始化,可以在定义变量的时候初始化,例如:struct stu s = {"nihao",28};


对于重点掌握的是结构体内存对齐问题。

结构题内存的开辟像数组一样,在栈中开辟一段内存,从小到大依次分配。
而首成员的地址就是结构体的地址。

那么如何来计算结构体大小?那就要熟悉结构体中内存的对其规则:

有以下四点:

1.第一个成员在结构体变量偏移量为0的地方初。也就是说第一个成员地址与结构体地址相同。

2.其他成员变量要对其到某个对齐数的整数倍的地址处。

关于对齐数是编译器默认的一个对其数与该成员大小的比较值。在linux中默认对齐数为四,在vs中默认对齐数为八。当然也可以自己设定对齐数。

3.结构体总大小为最大对齐数的整数倍

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体整体大小就是所有最大对齐数的整数倍。


说完结构体内存对齐问题,来说说结构体传参问题。

就一句话,传参可以直接穿变量,但开销太大,所以传参一般传结构体地址。


位段与结构体类似,但是位段成员必须是int ,unsigned int ,signed int类型

位段就是一种用于节约内存空间的方法。

struct a
{
	int a:2;
	int b:5;
	int c:10;
	int d:30;
};

按照bit位来算,所以上面的结构体大小为8个字节。


枚举

顾名思义,就是一一列举,关键字为enum

enum
{
	a,
	b,
	c=9,
	d,
	e
};

a的值默认为0,b就等于1

而给c 赋值后d就等于10

用枚举的优点增加可读性和可维护性,防止命名污染。


联合体

联合体的特征就是成员公用了一段内存空间。

联合体的大小就是联合体内最大的成员大小。