目录
结构体与共用体
1、结构体(struct)
(1) 格式与用法
(2) 结构体允许嵌套
(3) 结构体成员初始化
(4) 指针替换变量
(5) 求结构体在内存空间所占字节
2、共用体(union)
(1) 格式与概念
(2) 应用
3、枚举类型(enum)
(1) 格式与概念
(2) 应用
4、typedef 类型
结构体与共用体
1、结构体(struct)
(1) 格式与用法
其中,标识符首字母必须大写(规定),最后一行的花括号后必须加分号“;”。用来定义新的数据类型,存放在声明部分中。
例如,创建一个 struct Student 数据类型:
struct Student
{int id;char name[20];float score;
};
对新的数据类型定义变量的方法:
a. 在末行花括号( } )与分号( ;)中间写入所需变量的个数及名称,此时变量为全局变量,存放在静态区;
b. 在主函数中输入创建数据类型名,在其后输入变量名来定义变量,此时变量为局部变量,存放在栈区。例如:
注意:
在主函数 main 中,成员类型与 struct 中的成员类型一致。
“ . ”为结构体成员运算符,是一级运算符,自左至右。
例如:使用创建的 struct Student 数据类型定义变量 s ,定义类型成员内容,完成 “1,zhangsan,97.500000” 的输出效果
int main(void)
{struct Student s;s.id = 1;strcpy(s.name, "zahngsan");//【1】s.score = 97.5;printf("%d,%s,%f\n", s.id,s.name,s.score);return 0;
}
值得注意的是代码中的【1】位置,不能写为“ s.name = "zhangsan" ”,数组不能直接进行赋值。
(2) 结构体允许嵌套
创建一个 struct Date 数据类型,结构体成员信息如下:
struct Date
{int year;int month;int day;
};
使用 struct Student 与 struct Date 两种数据类型,完成" 1, zhangsan, 97.500000, 2002-3-12 "的输出效果
struct Student
{int id;char name[20];float score;struct Date birthday;
};int main(void)
{struct Student s;s.id = 1;strcpy(s.name, "zhangsan");s.score = 97.5;s.birthday.year = 2002;s.birthday.month = 3;s.birthday.day = 12;printf("%d, %s, %f,%d-%d-%d \n", s.id, srname, s.score, s.birthday.year, s.birthday.month, s.birthday.day);return 0;
}
(3) 结构体成员初始化
a. 全初始化:结构体初始化与结构体成员声明顺序一致,例如:
struct Student s ={1, "zhangsan", 97.5, {2002,3,12}};
b. 部分初始化:只对部分成员信息做初始化,要修改的内容之间用逗号隔开
int main(void)
{struct Student s = {.id = 1,.score = 97.5,.birthday = {.year = 2002,.month = 3,}};printf("%d, %s, %f,%d-%d-%d \n", s.id, srname, s.score, s.birthday.year, s.birthday.month, s.birthday.day);return 0;
}
(4) 指针替换变量
通过指针可以对成员进行修改,效率更高,否则只是值传递
struct Student *p;
p = &s;
p->id += 10;
printf("%d %f\n", p->id, p->name);
//p->name 也可写为 (*p).id
//推荐 p->name
(5) 求结构体在内存空间所占字节
内存对齐:数据总线以数据类型的整数倍都数据(整除)。
1、默认按照CPU位数对其(8)字节,最终大小必须是8的整数倍;
2、在结构体成员中找到最长成员,最终按照该成员长度对其;
3、按照结构体声明的顺序,依次将成员保存到结构体内存中,保存的偏移量 / sizeof(成员类型)。
例如:struct Dome 中的成员数据类型依次为 char(黄)、int(蓝)、short(橙),存储如下,又因为要被最长的整除(int 的4个字节),所有该类型的 sizeof 为12。
(6) 应用
对于 struct Student 中的成员信息
struct Student
{int id;char name[20];float score;
};
eg1. 单项输出(printStudent),全部输出(printStudents)
void printStudent(struct Student *p)
{printf("%d, %s, %f\n", p->id, p->name, p->score);
}void printStudents(struct Student a[], int len)
{int i;for(i = 0;i < len;++i){printStudent(a + i);}
}
eg2. 交换(swap),逆序(reverseStudents)
void swap(struct Student *a, struct Student *b)
{struct Student t;t = *a;*a = *b;*b = t;
}void revserseStudents(struct Student *a, int len)
{int i;for(i = 0;i < len / 2;++i){swap(a + i, a + len - i - 1);}
}
eg3. 采用回调函数按名字长度(namecmp)、按成绩(scoreStudent)进行排序(sortStudent)
int namecmp(struct Student *p1, struct Student *p2)
{return strcmp(p1->name, p2->name);
}int scorecmp(struct Student *p1, struct Student *p2)
{if(p1->score > p2->score){return 1;}else if(p1->score == p2->score){return 0;}else{return -1;}
}void sortStudent(struct Student *a, int len, int (*pfn)(struct Student *, struct Student *))
{int i, j;for(i = 0;i < len - 1;++i){for(j = i + 1;j < len;++j){if(pfn(a + i, a + j) > 0){swap(a + i, a + j);}}}
}
在主函数中的书写格式
int main(void)
{struct Student a[3] = {{1, "zhangsan", 97.5},{2, "lisi", 98},{3, "wanghu", 95}};int len = sizeof(a) / sizeof(*a);sortStudent(a, len, namecmp);printStudents(a, len);return 0;
}
* 结构体之间不能进行比较排序,但结构体成员之间可以进行比较排序。
2、共用体(union)
(1) 格式与概念
其中,共用体名满足标识符要求,且首字母要大写,共用体成员的内存公用,该类型代码存放在声明中,
创建 union Demo 数据类型,说明共用体成员的内存是共用的
union Demo
{int i;short s;char c;
};
int main(void)
{ union Demo d;d.i = 1000;d.s = 100;d.c = 10;printf("%u\n", sizeof(d));//输出结果为 4printf("%d\n", d.i);//输出结果为 10return 0;
}
说明:内存共用并且会进行覆盖,i 为int型占4个字节,short占2个字节,char占1个字节,相当于int 先占了第一二三四个格子,short 占第一二个格子,char占第一个格子,覆盖到最后只剩 char 的一个格子,输出。
可以运用指针作为类型变量
int main(void)
{union Demo *p;p = &d;printf("%p %p %p\n", &d.i, &d.s, &d.c); return 0;
}
(2) 应用
用来判断程序大小端存取
union Demo
{int i;char c;
};int main(void)
{union Demo d;d.i = 1;if(d.c == 1){puts("little");}else{puts("big");}return 0;
}
3、枚举类型(enum)
(1) 格式与概念
枚举类型(enum),用来自定义一个数据类型,并将常参放入其中。
一般格式为:
其中,标识符首字母依旧要大写,该类型的所有可能取值称为“枚举类型常量”,各取值之间用逗号“,”隔开,最后一个取值后面不需要加任何东西,花括号后的分号“;”不能省略。也可以对其输出变量(eg1. 中的 w )进行偏移(加法)。例如:
创建 enum Week 类型,并将 Week 的所有可能放入其中,并对 w 的后一项进行输出(可以用 “%d” 进行输出),输出的值为变量 w 在枚举常量的位置,也可以对常量进行赋值,但不能重复(例如下图 Tue=7)
enum Week
{Sun, Mon, Tue = 7, Wes, Thu, Fri, Sat
};int main(void)
{enum Week w;w = Sun;printf("%d\n", w + 1);//输出为 Monreturn 0;
}
(2) 应用
该类型可以做 switch 函数后面的表达式,例如:(可自行补充其他 case 情况)
enum Week
{Sun, Mon, Tue, Wes, Thu, Fri, Sat
};int main(void)
{enum Week w;switch(w){case Sun:puts("lol");break;case Mon:case Tue:puts("study");break;default:break;}return 0;
}
4、typedef 类型
将已有类型的类型名换个名字,在全局区起名,将变量名变为类型的类型名。在全局区起名。可以在数据类型(int、char、short等后加,也可以在struct、union、enum后加),类型名可以是一个标识符,也可以是一个数组,例如:
typedef int INT;
typedef int ARRAY[10];int main(void)
{int i;ARRAY a;printf("%lu\n", sizeof(a));return 0;
}
也可以运用指针作为类型名,例如:
typedef struct Demo
{int i;short s;char c;
}Demo, *PDEMO;int main(void)
{Demo d;PDEMO p;p = &d;return 0;
}
【END】
、