赞
踩
目录
结构体:由变量组成的数据类型。
- //创建「人」的数据类型
- struct People //「struct People」为数据类型名,其中「struct」固定,「People」自定义
- {
- char name[10];//姓名
- int age;//年龄
- };
- struct
- {
- char name[10];
- int age;
- };
当用特殊声明创建多个结构体时,编译器将全部视为不同类型。
例:用特殊声明创建 2 个一样的结构体,创建变量后进行赋值。
(1)主函数内创建变量(局部变量)
struct People p1, p2;
struct People* p1, *p2;//指针变量
(2)声明结构体时创建变量(全局变量)
- struct People
- {
- char name[10];
- int age;
- }p1,p2;//创建「p1」「p2」两个「struct People」类型的变量
- struct People
- {
- char name[10];
- int age;
- }*p1,*p2;//创建「p1」「p2」两个「struct People」类型的指针变量
错误:
- struct People
- {
- char name[10];
- int age;
- struct People p;
- };
当 People 中创建了 p 时,p 里面还会包含一个 p,不断循环下去,导致计算不出占用内存大小,所以编译器报错。
正确:
- struct People
- {
- char name[10];
- int age;
- struct People *p;
- };
当用指针的方式进行自引用,只需提供一个固定的指针类型大小就可以了。
特殊声明不可进行自引用
将 struct 进行重定义之后,编译器还是会将创建出来的不同变量视为不同类型。
- typedef struct People
- {
- char name[10];
- int age;
- }P;
- //将「struct People」重定义为「P」
(1)一般初始化
- struct People
- {
- char name[10];
- int age;
- };
-
- struct People p = { "张三",18 };
或
- struct People
- {
- char name[10];
- int age;
- }p = { "张三",18 };
(2)嵌套初始化
- struct A
- {
- int b;
- };
-
- struct People
- {
- char name[10];
- int age;
- struct A a;
- };
-
- struct People p = { "张三",18 ,{0} };
- //因为p中的a是结构体,所以也需要使用{}
用空间换取时间
作用:
(1)提高可移植性,某些平台只能在特定地址取出特定数据类型。
(2)提高性能:有时访问未对齐内存可能要比对齐内存多访问一次,因为内存对齐后,系统就知道从哪开始访问获取该数据。
内存对齐规则:
(1)所有成员须对其到对齐数的整数倍偏移量处
(2)结构体总大小为成员最大对齐数的整数倍
(3)数组或嵌套结构体的偏移量为自身内变量的最大偏移量
对齐数:该成员占用字节数,VS 下最大不超过8
偏移量:内存单位与起始位置的距离
集中占用空间小的成员可以节约空间
例 1:
- struct X
- {
- char c1;
- int i;
- char c2;
- }x;
-
- struct Y
- {
- char c1;
- char c2;
- int i;
- }y;
-
- int main()
- {
- sizeof(x);
- sizeof(y);
-
- return 0;
- }
答案:12、8
例 2:
- struct X
- {
- char c1;
- int i;
- char c2;
- };
-
- struct Y
- {
- char c1;
- char c2;
- struct X x;
- char c3;
- }y;
-
- int main()
- {
- sizeof(y);
-
- return 0;
- }
答案:20
使用 offsetof 可查看结构体类型中变量所在偏移处,需包含头文件 < stddef.h>
例:
- struct X
- {
- char c1;
- int i;
- char c2;
- }x;
-
- struct Y
- {
- char c1;
- char c2;
- struct X x;
- char c3;
- }y;
-
- int main()
- {
- printf("%d\n", sizeof(y));
- printf("%d\n", offsetof(struct Y, c1));
- printf("%d\n", offsetof(struct Y, c2));
- printf("%d\n", offsetof(struct Y, x));
- printf("%d\n", offsetof(struct Y, c3));
-
- return 0;
- }
例:
- #pragma pack(1)//将最大对齐数改为1
- struct X
- {
- char c1;
- int i;
- char c2;
- }x;
- #pragma pack()//将最大对齐数改回默认值
(1)值传递
- struct A
- {
- int i;
- };
-
- void print(struct A a)
- {
- printf("%d", a.i);
- }
-
- int main()
- {
- struct A a = { 1 };
- print(a);
-
- return 0;
- }
(2)地址传递
- struct A
- {
- int i;
- };
-
- void print(struct A* a)
- {
- printf("%d", a->i);
- }
-
- int main()
- {
- struct A a = { 1 };
- print(&a);
-
- return 0;
- }
函数传参时需要进行压栈,如果参数过大会导致不必要的时间、空间消耗,所以结构体传参时,地址传递优于值传递。
声明结构体时,在其中的成员后加上为该成员分配的内存(以位为单位),该结构体成员称为位段。
例:
- struct S
- {
- int a : 3;//给a分配3个比特位
- int b : 4;//给b分配4个比特位
- int c : 5;//给c分配5个比特位
- int d : 4;//给d分配4个比特位
- };
(1)位段只能是整型
(2)位段以不同整型大小按需开辟空间
例:
- struct S
- {
- int a : 3;
- int b : 4;
- int c : 5;
- int d : 4;
- };
-
- int main()
- {
- struct S s = { 0 };
- s.a = 10;
- s.b = 12;
- s.c = 3;
- s.d = 4;
-
- return 0;
- }
位段不可跨平台
(1)int 类型被当做有符号或无符号不确定
(2)位数不确定(16 为机器下 int 为 2 字节)
(3)内存从左向右分配或相反,尚未确定
(4)开辟新空间时,旧空间利用或舍弃未确定
位段应用在数据报文中,因为报文中每个字段所需空间极小。
所有成员共用同一片空间的数据类型叫联合。
联合的声明、变量创建同结构体一样,只需将结构体中的「struct」替换为「union」
例:
- union U
- {
- int i;
- char c;
- }u;
-
-
- int main()
- {
- printf("%d\n", &(u.i));
- printf("%d\n", &(u.c));//(1)
-
- u.i = 0x11223344;
- u.c = 0x55;
- printf("%x\n", u.i);//(2)(小端环境下)
-
- return 0;
- }
结果:
(1)2 个地址相同
(2)44332200
联合的大小为最大成员大小且为成员内最大对齐数的倍数
例 1:
- union U
- {
- char c[5];
- int i;
- }u;
- int main()
- {
- printf("%d\n", sizeof(u));
- return 0;
- }
答案:8
最大成员大小为 5(char [5]),最大对齐数为 4(int)
例 2:
- union U
- {
- short c[7];
- int i;
- }u;
- int main()
- {
- printf("%d\n", sizeof(u));
- return 0;
- }
答案:16
最大成员大小为 5(short [7]),最大对齐数为 4(int)
枚举的作用类似 define,但是枚举将定义的常量有类型且以类型分组。
例:
- enum Colour//颜色
- {
- BLUE,
- GREEN,
- RED
- };
-
- enum Sex//性别
- {
- MAN,
- WOMAN
- };
枚举内成员的值默认从 0 开始递增,可自定义。
例 1:
- enum Colour
- {
- BLUE,
- GREEN,
- RED
- };
-
- int main()
- {
- printf("%d", BLUE);
- printf("%d", GREEN);
- printf("%d", RED);
- return 0;
- }
结果:0、1、2
例 2:
- enum Colour
- {
- BLUE=1,
- GREEN,
- RED=5
- };
-
- int main()
- {
- printf("%d", BLUE);
- printf("%d", GREEN);
- printf("%d", RED);
- return 0;
- }
结果:1、2、5
例:
- enum Colour
- {
- BLUE=,
- GREEN,
- RED=
- };
-
- int main()
- {
- enum Colour c;
- c = GREEN;
- return 0;
- }
错误用法:
- enum Colour
- {
- BLUE,
- GREEN,
- RED
- };
-
- int main()
- {
- enum Colour c;
- c = 1;
- return 0;
- }
因为 1 是整型,而 c 是 enum Colour 类型,不同类型不能进行赋值。
(1)可一次性定义多个常量
(2)有类型,更严谨
(3)便于调试,程序执行前的预编译会进行宏替换,从而不能观察到 define 定义的值
(4)增加代码可读性
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。