目录
一、结构体
1.结构体的声明:
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不用类型的变量
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号是自带的
在声明结构的时候,可以不完全的声明。
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
2.结构体自引用:
在结构中包含一个类型为该结构本身成员是不可以的
struct Node
{
int data;
struct Node next;
};
正确的自引用方式:
struct Node
{
int data;
struct Node* next;
};
3.结构体变量的定义和初始化:
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
struct Stu //类型声明
{
char name[15];//名字
int age; //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
4.结构体内存对齐:
对齐规则:vs中默认对齐规则是8(但是可以改默认对齐数:#pragma cpack(4))
(1)第一个成员在与结构体变量偏移量为0的地址处。
(2)其他成员变量要对齐到某个数字的整数被的地址处。
(3)结构体总大小为最大对齐数的整数倍。
(4)如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐的整数倍,结构体的整体大小就是所有最大对数的整数倍。
为什么存在内存对齐?
(1)平台原因:不是所有的硬件平台都能访问在任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
(2)性能原因:数据结构应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐访问仅需要一次访问。
总的来说:结构的内存对齐是拿空间换取时间
struct S1
{
char c1;
int i;
char c2;
};
struct S2
{
char c1;
char c2;
int i;
};
5. 修改默认对齐数:
之前我们见过了 #pragma 这个预处理指令,这里我们再次使用,可以改变我们的默认对齐数。
6.结构体传参:
结构体传参的方法有两个
struct S
{
int data[1000];
int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传地址
return 0;
}
但是一般首选print2,因为函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
二、枚举类型
1.枚举类型的定义:
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};
枚举故名意义就是意义列举,像上面列出来的enum Day,enum Sex,enum Color都是枚举类型。{}中的内容是枚举类型的可能取值,也叫 枚举常量 。
可以看出默认从0开始,赋值之后也是依次递增的。
2 枚举的优点:
3 枚举的使用:
enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
clr = 5;
三、 联合类型(共用体)
1. 联合类型的定义:
2. 联合的特点: