自定义类型:结构体,枚举,联合体
结构体的基础知识
结构体是一些值的集合
struct tag
{
member_list;
}variable-list;
struct Stu
{
char name[20];
int age;
double score;
};
struct Book
{
char name[20];
float price;
char id[12];
};
struct Stu s1;//全局
int main()
{
struct Stu s2;//局部
return 0;
}
特殊的声明
struct //匿名结构体 ,这里只能用一次
{
char name[20];
char id[12];
}ss;
struct
{
char name[20];
char id[12];
}a[20],*p;
// p = &ss //err 匿名结构体的成员如果一样,在编译器看来也是不同的类型的结构体
结构的自引用
数据域:存放数据的区域
指针域:存放下一个节点的地址
struct Node
{
int data;//数据
//struct Node n;//error
struct Node * next;//最后一个地址是NULL
};
typeof struct Node //typeof 是类型重命名
{
int data;
struct Node* next;
}Node,* pNode;
//pNode --> struct Node*
int main()
{
struct Node n1;
Node n2; //n2与n1类型一样
}
结构体创建与初始化
struct Book
{
char name[20];
float price;
char id[20];
}s={"c语言",55.5f,"PGC001"};
struct Node
{
struct Book b;
struct Node* next;
};
int main()
{
struct Book s2 = {"love2study",66.6f,"bbd"};
struct Node n = {{"Java",66.8,"TG001"},NULL};
return 0;
}
结构体内存对齐
-
第一个成员放在结构体内存偏移量为0的地址处
-
其他成员要对齐到某个数字(对齐数)的整数倍的地址处
对齐数 = 编译器默认的一个对齐数与该成员大小的较小值
-
结构体的总大小必须为最大对齐数(每个成员变量都有自己的对齐数)的整数倍
-
如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
struct S1
{
char c1;
int i;
char c2;
};//12个字节
struct S2
{
char c1;
char c2;
int i;
};//8个字节
//offsetof //<stddef.h>
//size_t offsetof( structName, memberName );
//计算结构体成员相对于起始地址的便宜量
修改默认对齐数
#pragma pack(4)//设置 一般2的几次方
struct S
{
char c;
double d;
};
#pragma pack()//取消 中间的结构体就是按照更改的对齐数来排序
位段
-
位段的成员必须是int,unsigned int ,signed int.
-
位段的成员名后边有一个冒号和一个数字。
struct A
{
int _a:2; //_a这个成员只占2个bit位
int _b:5; //_b这个成员只占5个bit位
int _c:10; //_c这个成员只占10个bit位
int _d:30; //_d这个成员只占30个bit位
};
位段的开辟空间
-
位段的成员可以是int,unsigned int,signed int 或者是char类型
-
位段的空间上是按照需要以四个字节(int)或者是1个字节(char)的方式来开辟的。
-
位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段。
枚举
enum Sex
{
MALE,//0
FEMALE,//1
SECRET,//2
};// 枚举的可能
enum Day
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun,
};
int main()
{
enum Sex s = MALE;
enum Sex s2 = FEMALE:
enum Day d =Fri;
}
// 枚举的值: 默认是从0开始,一次递增1,定义的时候也可以赋初值
联合(共用体)
联合的定义
包含一系列的成员,这些成员共有一块空间
nion Un
{
char c; //1
int i; //4
};
int main()
{
union Un u;
printf("%d\n",sizeof(u));//4
printf("%p",
printf("%p",(
printf("%p",(
//三个地址值相同
return 0;
}
// 不会同时出现的时候可以选择联合体
联合的特点
利用联合体判断大小端:
int check_sys()
{
union Un
{
cahr c;
int i;
};
c.i = 1;
return u.c;
}
int main()
{
if (1 == check_sys())
printf("小端\n");
else
printf("大端\n")
return 0;
}
联合体也存在内存对齐的情况
union Un
{
char arr[5];//看类型,都是1
int i;
};//内存是8个字节,存在内存对齐