C语言 自定义类型 结构体 枚举 共用体(联合)

文章目录

  • 1.结构体
    • 1.1结构体声明
    • 1.2结构体变量定义与初始化
    • 1.3结构体内存对齐
      • 练习题
    • 1.4修改默认对齐数
    • 1.5结构体传参
  • 2.位段
  • 3.枚举

1.结构体

描述一些复杂对象时经常用到结构体,结构体是c语言自带类型的集合

1.1结构体声明

比如一个学生类型的定义

struct Stu
{
	char name[20];
	int age;
	int id;
}S1;

struct是结构体关键词,后面跟着要结构体类型,可以理解为标签,是将该结构体类型区别与其它结构体类型的符号。接着是大括号,里面是结构体成员,可以是自带类型,也能是自定义类型,不过不能赋初值,只是一个类型的声明。S1是该结构体类型的一个变量,属于全局变量。注意在声明最后要写一个分号,并且结构体不能自引用,也就是不能包含自己。

struct
{
	int a;
	char b;
	float c;
}x;
struct
{
	int a;
	char b;
	float c;
}a[20], * p;


还有一种特殊声明,就是不写结构体名称,这种声明的变量创建只能在最后的分号之前创建。现有语句p = &x,该表达式是否合法?编译器会将两个声明当成两个不同的结构体类型,两个不同类型当然不能这样赋值。

1.2结构体变量定义与初始化

struct Stu
{
	char name[20];
	int age;
};

int main()
{
	struct Stu s = { "zhangsan",18 };
	return 0;
}

struct Stu是一种类型像int一样,接着是结构体变量名,用大括号初始化结构体,里面的元素用逗号隔开。

1.3结构体内存对齐

内存对齐规则

  1. 第一个成员储存在偏移量为0的地址处。偏移量是指与结构体首成员之间
    相差的成员个数。
  2. 其他结构体成员总是存储到对齐数的整数倍的地址处。对齐数:编译器默认对齐数(有的编译器没有,vs为8)与成员大小的较小值。
  3. 结构体大小为最大对齐数的整数倍
  4. 如嵌套了结构体,嵌套的结构体存储到自己的最大对齐数的整数倍处

练习题

struct S1
{
	char c1;
	int i;
	char c2;
};

c1先占用一个字节,但i为整形对齐数为4,存储到偏移量为4的倍数的地址处,浪费了3字节,整形存储又用了4个字节,c2对齐数为1,占用1字节,结构体大小为最大对齐数的整数倍,现在结构体为9字节,最后结构体为12字节,4的整数倍。


struct S2
{
	char c1;
	char c2;
	int i;
};

c1与c2占用2字节,i对齐到偏移量为4的整数倍处,浪费2字节,最后为8字节。

struct S3
{
	double d;
	char c;
	int i;
};

double8字节,char1字节,int对齐时浪费3字节,自己时4字节,此时16字节,为最大对齐数8的整数倍。

struct S4
{
 char c1;
 struct S3 s3;
 double d;
};

c1占用1字节,s3为结构体,s3的最大对齐数为8,浪费7字节,加上自己16字节,d是8字节,最后是32字节。

1.4修改默认对齐数

#pragma pack(n)//将默认对齐数修改成n

#pragma pack()//将默认对齐数重置回原来的值

1.5结构体传参

当我们用结构体传参时,尽量使用结构体指针,当结构体太大时,作为实参的临时拷贝的形参会占用较多的空间,造成空间的浪费。我们在结构体传参时尽量使用指针。

2.位段

位段的成员必须是signed int,unsigned int,或者char。位段的空间是按照1个或4个字节开辟的。

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

在结构体成员后加上冒号与数字来表示该成员所占的位。因为是char先开辟一个字节,a使用3个bit,b使用4个bit,c要使用5
个bit,有的编译器会将剩下的一个bit使用,有的则会再开辟一个字节来存放c。假设vs会再开辟一个字节,存放d时因为放不下又开辟一个字节。所以S结构体大小是3个字节。(冒号后的数字不能大于类型)C语言 自定义类型 结构体 枚举 共用体(联合)_第1张图片
但位段存在许多跨平台问题
1.int位段被当作无符号还是有符号是不确定的
2.位段中最大位的数目不能确定,在16位机器与32位机器,在32位机器中写27换作16位机器会出现问题。
3.位段中成员是从左向右存储,还是从右向左标准还未定义。
4.当剩余空间无法存储下一个成员时,浪费剩余空间还是利用标准也未确定。

跟结构体相比,位段的空间更小,能很好地节省空间,但其跨平台性差。

3.枚举

enum Color//枚举的声明
{
	red,
	buld,
	green
};

括号中的成员称作枚举常量。C语言 自定义类型 结构体 枚举 共用体(联合)_第2张图片
枚举常量的值默认从0开始递增,也可以之间在其后面赋值。C语言 自定义类型 结构体 枚举 共用体(联合)_第3张图片

你可能感兴趣的:(【C语言】学习总结,c语言,开发语言,后端)