一.结构体
1.结构体类型的声明
srruct tag { nemer-list;//成员列表 }varible-list;//变量列表
结构体在声明的时候,可以不完全声明。
例如:描述一个学生
struct stu { char name[20];//名字 int age;//年龄 char sex[20];//性别 };//分号不能省略
2.结构体变量的创建和初始化
struct point { int x; int y; }p1;//声明类型的同时,定义变量p1 struct point p2 = { 10,20 };//定义结构体变量p2,并初始化 struct stu { char name[20]; int age; }; struct stu s1 = { "zahngsan",20 };//初始化 struct stu s2 = { .age = 20,.name = "wnagwu" };//指定初始化 //结构体嵌套初始化 struct Node { int data; struct point p; struct Node* next; }n1 = { 20,{4,5} ,NULL}; struct Node n1 = { 20,{4,5} ,NULL };
3.结构体成员访问操作符
3.1直接访问操作符(. ),接受两个操作数。
使用方式:结构体变量.成员名
3.2对于结构体的指针而言的间接访问操作符(->)。
使用方式:结构体指针->成员名
3.3解引用操作符(*)。
指向结构体类型变量的指针也可以通过.方式访问成员,只不过要先通过*对该指针解引用
#include <stdio.h> struct point { int x; int y; }; int main() { struct point p = { 3,4 }; struct point* ptr = &p; ptr->x = 10; ptr->y = 20; printf("x=%d y=%d\n", ptr->x, ptr->y); return 0; }
4.结构体内存对齐(计算结构体的内存大小)
首先得掌握对齐规则:
4.1.结构体成员的第一个成员对齐到和结构体起始位置偏移量为0的地址处.
4.2.其他成员的要对齐到某个数字(对齐数)的整数倍处.
对齐数=编译器默认的一个对齐数与该成员变量大小的较小值.
4.3.结构体总大小为最大对齐数(所有结构体成员中的最大对齐数)的整数倍.
4.4.如果结构体中嵌套了结构体,嵌套的结构体成员对齐到自己成员中最大对齐数的整数倍处
,结构体的整体大小就是所有成员中最大对齐数的整数倍处.
补充:
修改编译器的默认对齐数:
struct S { char c1; int i; char c2; }; int main() { struct S s = { 0 }; printf("%d ", sizeof(s)); return 0; }
注:
当然我们也可以通过使用#pragma pack( ) ,来修改默认的对齐数,与此同时也可以用它来取消修改。
5.结构体实现位段(内存针对的是比特位,会发生截断现象)
位段的声明和结构体的生命是类似的,有两个不同:
5.1 位段的成员必须是int,unsigned int ,或者signed int,在c99中位段成员的类型也可以选择其他类型。
5.2位段的成员的后边有一个冒号和一个数字。
二.联合体(共用体)
1.联合体的声明
#include <stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
//联合变量的定义
union Un u = { 0 };
//计算联合体变量的大小
printf("%d\n", sizeof(u));
return 0;
}
2.联合体的特点
联合体的成员是共用一块内存空间的,这样一个联合一体变量的大小,至少是最大成员的大小,(因为联合至少得有能力保存最大的那个成员)。
三.枚举(列举---把可能的值一一列举)
1.枚举类型的声明
enum color
{
red,
green,
blue
};
{ }中的内容是枚举类型的可能取值,也叫枚举常量。当然 ,在声明枚举类型的时候也可以赋初值。
2.枚举类型的优点:
2.1增加代码的可读性和可维护性.
2.2和define定义的标识符比较枚举有类型检查,更加严谨.
2.3便于调试,预处理阶段会删除#define定义的符号.
2.4使用方便,一次可以定义多个常量.
2.5枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内声明.
3.枚举类型的使用
enum color
{
red = 1,
green=2,
blue=4
};
enum color clr = green;//使用枚举常量给枚举变量赋值