enum枚举
枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
它是一种用户定义的数据类型,它用关键字enum以如下语法来声明:enum 枚举类型名字,{名字0,…,名字n};第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1 (这个是可以自定义成员值的)。
在C 语言中,枚举类型是被当做 int 或者 unsigned int 类型来处理的
枚举也是一种数据类型,所以它和基本数据类型一样也可以对变量进行声明,枚举也可以用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明。
1、同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。
2、枚举成员)是「常量」而不是变量,因为枚举成员是常量,所以不能对它们赋值,只能将它们的值赋给其他的变量。
3、枚举类型的定义和变量的声明分开:如果对枚举型的变量赋整数值时,需要进行类型转换。
struct 结构体
结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员,结构体也是一种数据类型,它由程序员自己定义,可以包含多个其他类型的数据。
声明定义结构体:
struct关键字+结构体的标志名+{大括号里边是成员}+后面的声明此结构变量+末尾分号
无名结构体: 可以定义无名结构体类型的变量。编译器对无名结构体的处理是随机生成一个不重复的变量名。
无名结构的定义方式就是定义无名结构体时必须定义该结构体类型的至少一个变量。
1、结构体本身并不会被作为数据而开辟内存,真正作为数据而在内存中存储的是这种结构体所定义的变量。
2、先声明结构体类型,再定义该类型的变量,声明结构体类型,不分配空间定义结构体类型变量,就要分配内存空间。
3、结构体变量不能相加,相减,也不能相互乘除,但结构体可以相互赋值,也就是说,可以将一个结构体变量赋值给另一个结构体变量。但是前提是这两个结构体变量的结构体类型必须相同。
4、结构体的运算:要访问整个结构,直接用结构变量的名字,对于整个结构,可以做赋值,取地址,也可以传递给函数参数。
结构体内存对齐
结构体的对齐规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8 Linux中的默认值为4
- 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
可以通过预编译命令#pragma pack(n)来改变这一系数,其中的n就是要指定的“对齐系数”。
结构体数组
指数组中的每个元素都是一个结构体。如struct student tp[10];
结构体数组的初始化与数值型数组的初始化是一样的,数值型数组初始化的方法和需要注意的问题在结构体数组的初始化中同样适用,因为不管是数值型数组还是结构体数组都是数组。
结构体指针
和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符。
strcut node *tp=&nb; 指针一般用->访问结构体里边的成员。
这 2 种形式是等价的: (*指针变量).成员名。 指针变量->成员名
结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间。结构体变量才包含实实在在的数据,才需要内存来存储。所以用一个结构体去取一个结构体名的地址,这种写法是错误的,也不能将它赋值给其他变量。
结构体数组的每一个元素都是一个结构体变量。如果定义一个结构体指针变量并把结构体数组的数组名赋给这个指针变量的话,就意味着将结构体数组的第一个元素(即第一个结构体变量的地址),也即第一个结构变量中的第一个成员的地址赋给了这个指针变量。
union 联合体
几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中 以关键字union声明的一种数据结构,这种被称作“共用体”类型结构,也叫联合体。
“联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间,一个结构体变量的总长度大于等于各成员长度之和。而在“联合”中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。
1、不能把共用体变量作为函数参数,也不能是函数带回共用体变量,但可以使用专用指向共用体变量的指针。
2、所有成员占用同一段内存,修改一制个成员会影响其余所有成员。
共用体的访问:共用体访问成员的值时一般使用点.运算符,指针时用->运算符(和结构体是一样的)。