C语言 结构体 共用体 枚举
一.结构体
结构体定义时需要先定义结构体类型,然后再用类型来定义变量。
结构体是用来解决数组所有的元素的类型必须一致缺陷的,可以将结构体理解为一个其中元素类型可以不相同的数组。
1 // 定义类型 2 struct people 3 { 4 char name[20]; 5 int age; 6 }; 7 8 // 定义类型的同时定义变量。 9 struct student 10 { 11 char name[20]; 12 int age; 13 }s1; 14 15 // 将类型struct student重命名为s1,s1是一个类型名,不是变量 16 typedef struct student 17 { 18 char name[20]; 19 int age; 20 }s1; 21
结构体变量中的元素访问方式:
只有一种,用 . 或者->的方式来访问。
1 struct score 2 { 3 int a; 4 int b; 5 int c; 6 }; 7 8 struct myStruct 9 { 10 int a; // 4 11 double b; // 8 12 char c; 13 }; 14 15 int main() 16 { 17 struct myStruct s1; 18 s1.a = 12; // int *p = (int *)&s1; *p = 12; 19 s1.b = 4.4; // double *p = (double *)(&s1 + 4); *p = 4.4; 20 s1.c = 'a'; // char *p = (char *)((int)&s1 + 12); *p = 'a'; 21 22 int a[3]; // 3个学生的成绩,数组方式 23 score s; // 3个学生的成绩,结构体的方式 24 25 s.a = 12; // 编译器在内部还是转成指针式访问 int *p = s; *(p+0) = 12; 26 s.b = 44; // int *p = s; *(p+1) = 44; 27 s.c = 64; // int *p = s; *(p+2) = 44; 28 }
结构体对齐:
对齐访问牺牲了内存空间,换取了速度性能。
1 struct mystruct1 2 { // 1字节对齐 4字节对齐 3 int a; // 4 4 4 char b; // 1 2(1+1) 5 short c; // 2 2 6 }; 7 8 typedef struct mystruct2 9 { // 1字节对齐 4字节对齐 10 char a; // 1 4(1+3) 11 int b; // 4 4 12 short c; // 2 4(2+2) 13 }MyS2; 14 15 typedef struct myStruct5 16 { // 1字节对齐 4字节对齐 17 int a; // 4 4 18 struct mystruct1 s1; // 7 8 19 double b; // 8 8 20 int c; // 4 4 21 }MyS5 22 23 int main() 24 { 25 printf("sizeof(struct mystruct1) = %d.\n", sizeof(struct mystruct1)); // 8 26 27 printf("sizeof(struct mystruct2) = %d.\n", sizeof(struct mystruct2)); //12 28 printf("sizeof(struct mystruct5) = %d.\n", sizeof(MyS5)); //24 29 30 return 0; 31 }
二.共用体
共用体union和结构体struct在类型定义、变量定义、使用方法上很相似。
共用体中的各个成员其实是一体的,彼此不独立,他们使用同一个内存单元。

union中的元素不存在内存对齐的问题,因为union中实际只有1个内存空间,都是从同一个地址开始的,所以不涉及内存对齐。
用union来测试机器的大小端模式:
1 #include <stdio.h> 2 3 // 共用体中很重要的一点:a和b存放都是从u1的低地址开始的。 4 // 假设u1所在的4字节地址分别是:0、1、2、3的话,那么a存放顺序自然就是0、1、2、3; 5 // b所在的地址是0而不是3. 6 union myunion 7 { 8 int a; 9 char b; 10 }; 11 12 // 如果是小端模式则返回1,小端模式则返回0 13 int is_little_endian(void) 14 { 15 union myunion u1; //1对应十六进制就是0x0000_0001 16 u1.a = 1; // 地址0的那个字节内是1(小端)或者0(大端) 17 return u1.b; 18 } 19 20 int main(void) 21 { 22 int i = is_little_endian(); 23 if (i == 1) 24 { 25 printf("小端模式\n"); //在X86下的Linux中验证是小端模式 26 } 27 else 28 { 29 printf("大端模式\n"); 30 } 31 32 return 0; 33 }
三.枚举
枚举本质就是int类型的常量,每个符号和一个常量绑定。
宏定义和枚举的区别:
枚举是将多个有关联的符号封装在一个枚举中(譬如一星期有7天,譬如一个月有31天,适合用枚举),而宏定义是完全散的。也就是说枚举其实是多选一。
1 #define MON 1 2 #define TUE 2 3 #define WED 3 4 #define THU 4 5 #define FRI 5 6 #define SAT 6 7 #define SUN 7
例如以上这些代码,看起来很多很复杂,如果用枚举的方式:
1 enum DAY{MON=1,TUE,WED, THU, FRI, SAT, SUN};
枚举变量的定义:
1 enum DAY{MON=1,TUE,WED,THU,FRI}; 2 enum DAY day; 3 enum DAY{MON=1,TUE,WED,THU,FRI}day;//也可以在定义枚举类型时一起定义 4 enum{MON=1, TUE, WED, THU, FRI, SAT, SUN}day;//可以省略枚举名称
示例:
1 #include <stdio.h> 2 enum DAY 3 { 4 MON=1, TUE, WED, THU, FRI, SAT, SUN 5 }; 6 int main() 7 { 8 enum DAY day; 9 day = WED; 10 printf("%d",day); 11 return 0; 12 }
1 #include <stdio.h> 2 enum DAY{ 3 MON=1, TUE, WED, THU, FRI, SAT, SUN 4 } day; 5 int main(){ 6 // 遍历枚举元素 7 for (day = MON; day <= SUN; day++) { 8 printf("枚举元素:%d \n", day); 9 } 10 }
1 #include<stdio.h> 2 enum DAY{MON=1, TUE, WED, THU=6, FRI, SAT, SUN}day; 3 int main(){ 4 for(day=MON;day<=SUN;day++){ 5 printf("%d\t",day); 6 } 7 return 0; 8 } 9 //以上的输出结果会变成 1 2 3 4 5 6 7 8 9
浙公网安备 33010602011771号