一、结构体
1.1:概念
1.1.1:为了将不同的数据整合成一个有机整体,以便于引用
1.1.2: C与C++
C语言面向过程 C++面向对象
1.1.3:定义方法1(仅声明) - struct 结构名{
- 类型说明符 成员名;
-
- ....
- (成员列表)
- };
- struct student {
- int num;
- char name[10];
- char sex;
- int age;
- float score;
- char addr[30];
- };
复制代码
1.1.4:定义方法2(声明的同时定义变量) - struct 结构名{
- 类型说明符 成员名;
-
- ....
- (成员列表)
- }变量名列表;
- struct student {
- int num;
- char name[10];
- char sex;
- int age;
- float score;
- char addr[30];
- }student1,student2;
复制代码
1.1.5:结构体变量的大小
1.1.5.1:例子1 - struct student {
- int num;
- char name[10];
- char sex;
- int age;
- float score;
- char addr[30];
- }student1,student2;
- int main() {
-
- printf("%d", sizeof(student1));
- return 0;
- }
- 结果:
- 56
复制代码
1.1.5.2:例子2 - struct student {
- int num;
- char name[10];
- char sex[5];
- int age;
- float score;
- char addr[30];
- }student1,student2;
- int main() {
-
- printf("%d", sizeof(student1));
- return 0;
- }
- 输出:
- 60
复制代码
1.1.5.3:分析过程
1.1.5.4:总结
1.1.6:定义方法3(无结构体名,直接定义变量) - struct {
- int num;
- char name[10];
- char sex[5];
- int age;
- float score;
- char addr[30];
- }student1,student2;
复制代码
1.1.7:定义变量
-
struct student 是结构体类型 - sizeof(student) 是错误的
- sizeof(struct student) 是正确的
复制代码
1.2:结构体变量的使用以及初始化
1.2.1:不能将结构体变量作为一个整体输入和输出
1.2.2:正确使用格式是: 结构体变量.成员
1.2.3:结构体变量初始化
1.2.3.1:定义时初始化 - struct data {
- int year;
- int month;
- int day;
- };
- struct people {
- int num;
- char name[20];
- struct data birthday;
- float score;
- }boy1 = { 123,"liukai",{2001,6,11},963.256 }, boy2 ;
- int main() {
-
- //printf("%d", sizeof(student1));
-
- //printf("please input num:");
- //scanf("%d", &boy1.num);
- //printf("please input name:");
- //scanf("%s", &boy1.name);
- //printf("please input birthday:");
- //scanf("%d%d%d", &boy1.birthday.year, &boy1.birthday.month, &boy1.birthday.day);
- //printf("please input score:");
- //scanf("%f", &boy1.score);
- printf("学号:%d\t姓名:%s\t生日:%d-%d-%d\t成绩:%f\n", boy1.num, boy1.name, boy1.birthday.year, boy1.birthday.month, boy1.birthday.day, boy1.score);
-
- boy2 = boy1;
- printf("%p\n", &boy1);
- printf("%p\n", &boy1.birthday);
- printf("%p\n", &boy2);
- return 0;
- }
- 分析:需要值得注意的是,嵌套结构体的初始化要拿个{}括起来;
- 在初始化嵌套结构体时,花括号的作用主要有两个:
- 1、区分嵌套结构体的初始化值和外层结构体的其他成员初始化值,
- 2、以及明确嵌套结构体自身成员的初始化顺序。
复制代码
1.2.3.2:常见错误 - //只能在定义的时候进行整个初始化
- case1:
- struct people {
- int num;
- char name[20];
- struct data birthday;
- float score;
- }boy1 = { 123,"liukai",{2001,6,11},963.256 }, boy2 ;
- case2:
- struct people boy3 = { 123,"liukai",{2001,6,11},963.256 }
- case3:
- struct people boy[2] = { { 123,"liukai",{2001,6,11},963.256 } ,{ 123,"liukai",{2001,6,11},963.256 } };
- //这种定义之后再进行整个初始化的行为是错的
- struct people boy[2];
- boy[0] = { 123,"liukai",{2001,6,11},963.256 };
- printf("学号:%d\t姓名:%s\t生日:%d-%d-%d\t成绩:%f\n", boy[0].num, boy[0].name, boy[0].birthday.year, boy[0].birthday.month, boy[0].birthday.day, boy[0].score);
- 分析:
- 后续试图通过 boy[0] = { 123,"liukai",{2001,6,11},963.256 };C 语言中,结构体变量初始化通常需要在定义时进行,或使用循环等逐个成员赋值的方式。
复制代码
1.3:结构体数组
1.3.1:定义
一个学生有好几个属性,但现在有十个学生;此时用的数组就是结构体数组。
1.3.2:初始化 - struct people boy[2] = { { 123,"liukai",{2001,6,11},963.256 } ,{ 123,"liukai",{2001,6,11},963.256 } };
复制代码- struct people {
- int num;
- char name[20];
- struct data birthday;
- float score;
- }boy[2] = { { 123,"liukai",{2001,6,11},963.256 } ,{ 123,"liukai",{2001,6,11},963.256 } };
复制代码
1.4:指向结构体类型数据的指针
1.4.1:定义
1.4.2:访问成员方式
-
结构指针变量->成员名 -
*(结构指针变量).成员名 - struct data {
- int year;
- int month;
- int day;
- };
- struct people {
- int num;
- char name[20];
- struct data birthday;
- float score;
- }boy[2] = { { 1234,"liukai",{2001,6,11},963.256 } ,{ 123,"liukai",{2001,6,11},963.256 } };
- struct people *pboy=&boy[1];
- printf("%d-%d-%d\n", pboy->birthday.year, pboy->birthday.month, pboy->birthday.day);
- 分析:
- 1、在pboy->birthday.year中,第二个地方使用.而不是->是因为birthday是结构体people中的一个成员,它本身是一个结构体类型(struct data),而不是一个指针。
- 2、*pboy.birthday.year这种写法也是错误的,必须是(*pboy).birthday.year
- 2.1、在C语言中,成员访问运算符->和.的优先级高于解引用运算符*。
- 2.2、表达式*pboy.birthday.year会被错误地解析,因为编译器会优先处理.运算符。编译器会先尝试访问pboy这个指针对象的birthday成员,而不是首先解引用指针。
复制代码
1.5:结构体做函数参数
1.5.1:用结构体变量做函数参数 - void dayin(struct people boy )
- {
- printf("%d", boy.num);
- }
复制代码
1.5.2:用结构体变量指针做函数参数 - void dayin(struct people *boy )
- {
- printf("%d", boy->num);
- }
复制代码
二:链表
2.1:动态存储分配
541069.png&pos_id=img-blXEHShX-1745762881147)
2.1.1: malloc
2.1.2: free
2.2:链表
2.2.1:概念
2.2.2:静态链表的建立 - struct score {
- int math;
- int english;
- };
- struct student {
- int num;
- struct score scr;
- struct student* next;
- };
- int main() {
- struct student stu1, stu2, * head,*temp;
- head = &stu1;
- stu1.next = &stu2;
- stu2.next = NULL;
- stu1.num = 1;
- stu1.scr.math = 100;
- stu1.scr.english = 10;
- stu2.num = 2;
- stu2.scr.math = 99;
- stu2.scr.english = 9;
- temp = head;
- while (temp != NULL) {
- printf("%d-",temp->num);
- printf("%d-",temp->scr.math);
- printf("%d\n", temp->scr.english);
- temp = temp->next;
- }
- return 0;
- }
复制代码
2.2.3:动态链表的建立
首先是当前结点的建立
case1:结束结点
case2:头节点
case3:后续节点
- 所谓动态链表的建立指的是在程序执行过程中,从无到有的建立起一个链表,即一个一个的开辟结点空间和输入结点数据,并建立起前后链接的关系
- #define _CRT_SECURE_NO_WARNINGS // 必须放在第一行!
- #include<stdio.h>
- #include<stdlib.h>
- struct score {
- int math;
- int english;
- };
- struct student {
- int num;
- struct score scr;
- struct student* next;
- };
- struct student* creat() {
- int n = 0;
- struct student* head, * p,*tail;
- head = p = tail = NULL;
- while (1) {
- //创建节点
- p = (struct student*)malloc(sizeof(struct student));
- //赋初始值
- printf("input your num:");
- scanf("%d", &p->num);
- printf("input your math:");
- scanf("%d", &p->scr.math);
- printf("input your english:");
- scanf("%d", &p->scr.english);
- p->next = NULL;
- //判断结束条件
- if (p->num == 0) {
- printf("input ending!\n");
- return head;
- }
- //全局增加
- n++;
- //指针移动
- if (n == 1) {
- head = p;
- tail = p;
- }
- else {
- tail->next = p;
- tail = p;
- }
- }
- }
- int main() {
- struct student* head, * p;
- head = p = NULL;
- head = p = creat();
- while (p != NULL) {
- printf("num-%d math-%d english-%d\n", p->num, p->scr.math, p->scr.english);
- p = p->next;
- }
- printf("out ending!\n");
- return 0;
- }
- 需要注意的点:
- 1、结点初始化的流程:
- p = (struct student*)malloc(sizeof(struct student));//创建结点空间并返回指针
- printf("please input num:\n");//输入成员值
- scanf("%d", &(p->num));
- printf("please input math:\n");
- scanf("%d", &(p->scr.math));
- printf("please input english:\n");
- scanf("%d", &(p->scr.english));
- p->next = NULL;//next指针初始化为空
- 2、如果是第一个结点;//头尾指针均指向头节点
- head = p;
- tail = p;
- 如果不是第一个结点://链接尾指针节点和当前初始化的结点,并且更新tail指针
- tail->next = p;
- tail = p;
- 3、在&(p->scr.math)中,括号()是为了改变运算顺序,确保p->scr.math先被解析为一个完整的表达式,然后再取它的地址。
- 在&p->scr.math中,->运算符的优先级高于&,所以p->scr.math也会先被解析为一个完整的表达式,然后再取它的地址。
- 4、malloc的返回值是void*,必须要加一个强制转换
- 5、总结流程:
- 开始:
- 5.1:初始化变量:
- n = 0(全局变量,记录节点数)。
- head = NULL(头指针初始化为NULL)。
- tail = NULL(尾指针初始化为NULL)。
-
- 5.2:循环开始:
- 5.2.1:创建新节点p,并初始化成员值及next指针。
- 5.2.2:判断当前节点是否为结束节点:
- 是:跳出循环。
- 否:继续下一步。
- 5.2.3:n++(节点计数加1)。
- 5.2.4:判断是否为第一个节点:
- 是:
- head = p(设置头指针为当前节点)。
- tail = p(设置尾指针为当前节点)。
- 跳回循环开始。
- 否:
- 更新尾指针:tail->next = p(将新节点链接到尾部)。
- 更新尾指针为当前节点:tail = p。
- 跳回循环开始
- 6、一定记得加入头文件stdlib
复制代码
2.2.4: 为什么要进行malloc动态分配内存
如果使用如下代码: - struct student* creat() {
- int n = 0;
- struct student* head, * p,*tail;
- head = p = tail = NULL;
- while (1) {
- //创建节点
- struct student stu;
- p = &stu;
- //p = (struct student*)malloc(sizeof(struct student));
- //赋初始值
- printf("input your num:");
- scanf("%d", &p->num);
- printf("input your math:");
- scanf("%d", &p->scr.math);
- printf("input your english:");
- scanf("%d", &p->scr.english);
- p->next = NULL;
- //判断结束条件
- if (p->num == 0) {
- printf("input ending!\n");
- return head;
- }
- //全局增加
- n++;
- //指针移动
- if (n == 1) {
- head = p;
- tail = p;
- }
- else {
- tail->next = p;
- tail = p;
- }
- }
- }
复制代码- 用上述代码分析如下:
- 调用 creat() 函数时:
- +-------------------+
- | creat() 栈帧 |
- | (局部变量 stu) |
- | stu --> 数据 |
- +-------------------+
- 函数返回后:
- +-------------------+
- | creat() 栈帧 | --> 已被销毁
- +-------------------+
- head 指向已销毁的 stu
复制代码- 用malloc分析:
- 调用 creat() 函数时:
- +--------------------------------+
- | creat() 栈帧 |
- | |
- | head --> [堆内存] --> 节点1 |
- | tail --> [堆内存] --> 节点1 |
- | p --> [堆内存] --> 节点1 |
- | |
- | 节点1 --> 节点2 --> ... |
- | |
- +--------------------------------+
- 函数返回后:
- +--------------------------------+
- | main() 栈帧 |
- | |
- | head --> [堆内存] --> 节点1 |
- | p --> [堆内存] --> 节点1 |
- | |
- | 节点1 --> 节点2 --> ... |
- | |
- +--------------------------------+
- 内存释放:
- +--------------------------------+
- | main() 栈帧 |
- | |
- | 调用 free(head) |
- | |
- | head --> NULL |
- | p --> NULL |
- | |
- +--------------------------------+
复制代码
特性 | 栈内存 | 堆内存 |
---|
管理方式 | 编译器自动管理 | 程序员手动管理 | 分配效率 | 高效(通过指针调整) | 相对低效(涉及更多的内存管理操作) | 生命周期 | 与作用域绑定 | 程序员控制 | 使用场景 | 局部变量、短期存储 | 动态数据结构、长期存储 | 风险 | 无(编译器处理) | 内存泄漏、悬空指针 |
2.2.5:链表结点的删除
case1: head为空,,即链表为空
case2:删除头节点,只需要移动head指针
case3:删除后面结点,需要移动q->next指针(一定要确保p不为NULL)
case4:未找到删除结点
case3和case4需要通过一个while去遍历,再利用一个if判断排除case4 - struct student* delete(struct student *head,int delete_num) {
- if (head == NULL) {
- printf("list is empty!\n");
- return NULL;
- }
- if (head->num == delete_num) {
- head = head->next;
- return head;
- }
- else {
- struct student* p=head->next;
- struct student* q = head;
- if (p == NULL) {
- printf("delete error!\n");
- return head;
- }
- while (p->num != delete_num&&p->next!=NULL) {
- q = p;
- p = p->next;
- }
- if (p->num == delete_num) {//这种情况包含了p->next!=NULL和p->next==NULL两种情况,但处理步骤是相同的
- q->next = p->next;
- }
- else {//这种情况只包含了一种情况p->num != delete_num&&p->next==NULL,说明未找到
- printf("delete fail!!\n");
- }
- }
- return head;
- }
- int delete_num;
- printf("please input delete_num:");
- scanf("%d", &delete_num);
- head=delete(head,delete_num);
- 分析:
- 1、注意要返回head指针
- 2、如果删除的是头指针要进行特殊处理
- 3、q指针的含义是要删除节点的前一个指针,p是要删除的当前指针
- 4、要考虑到未找到删除结点的情况,即p->num!=XX&&p->next==NULL
- 5、head为NULL则直接返回
复制代码
2.2.6:动态链表的插入
case1: head为空,说明链表为空,直接令head=add_node
case2: 插入第一个结点,需要改变add_node->next指针,再令head=add_node
case3: 插入中间结点。需要改变q,p的值(一定要确保p不为NULL)
case4:插入表尾结点,只需要改变p->next=add_node
case3和case4需要通过一个while去遍历,再利用一个if判断排除case4 - struct student* add(struct student* head, struct student* add_node) {
- if (head == NULL) {
- return add_node;
- }
- if (head->num > add_node->num) {
- add_node->next = head;
- return add_node;
- }
- struct student* q, * p;
- q = head;
- p = head->next;
-
- if (p == NULL) {
- head->next = add_node;
- return head;
- }
- while (p->num < add_node->num&&p->next!=NULL) {
- q = p;
- p = p->next;
- }
- if (p->num > add_node->num) {
- q->next = add_node;
- add_node->next = p;
- }
- else {
- p->next = add_node;
- }
- return head;
- }
- struct student* padd_node;
- padd_node = (struct student*)malloc(sizeof(struct student));
- printf("please input add_node num:");
- scanf("%d", &padd_node->num);
- printf("please input add_node math:");
- scanf("%d", &padd_node->scr.math);
- printf("please input add_node english:");
- scanf("%d", &padd_node->scr.english);
- padd_node->next = NULL;
- head = add(head, padd_node);
复制代码
2.2.7:链表的查找
case1: head为空,直接返回null
case2:能找到
case3:到末尾了找不到返回NULL
case2和case3还是通过一个while先进行一个遍历,再根据一个if来进行区别 - struct student* search(struct student* head, int search_num) {
- struct student * p = head;
- if (head == NULL) {
- return NULL;
- }
- while (p->num != search_num&&p->next!=NULL) {
- p = p->next;
- }
- if (p->num == search_num) {
- return p;
- }
- else {
- return NULL;
- }
- }
- struct student* psearch;
- int search_num;
- printf("please input search_num:");
- scanf("%d", &search_num);
- psearch = search(head, search_num);
- if (psearch != NULL) {
- printf("num-%d math-%d english-%d\n", psearch->num, psearch->scr.math, psearch->scr.english);
- }
- else {
- printf("search error!!\n");
- }
复制代码
2.2.8:链表一系列操作完整代码(第一份代码有BUG,分析两份代码) - #define _CRT_SECURE_NO_WARNINGS // 必须放在第一行!
- #include<stdio.h>
- #include<stdlib.h>
- struct score {
- int math;
- int english;
- };
- struct student {
- int num;
- struct score scr;
- struct student* next;
- };
- struct student* creat() {
- int n = 0;
- struct student* head, * p,*tail;
- head = p = tail = NULL;
- while (1) {
- //创建节点
- p = (struct student*)malloc(sizeof(struct student));
- //赋初始值
- printf("input your num:");
- scanf("%d", &p->num);
- printf("input your math:");
- scanf("%d", &p->scr.math);
- printf("input your english:");
- scanf("%d", &p->scr.english);
- p->next = NULL;
- //判断结束条件
- if (p->num == 0) {
- printf("input ending!\n");
- return head;
- }
- //全局增加
- n++;
- //指针移动
- if (n == 1) {
- head = p;
- tail = p;
- }
- else {
- tail->next = p;
- tail = p;
- }
- }
- }
- struct student* delete(struct student *head,int delete_num) {
- if (head == NULL) {
- printf("list is empty!\n");
- return NULL;
- }
- if (head->num == delete_num) {
- head = head->next;
- return head;
- }
- else {
- struct student* p=head->next;
- struct student* q = head;
- while (p->num != delete_num&&p->next!=NULL) {
- q = p;
- p = p->next;
- }
- if (p->num == delete_num) {
- q->next = p->next;
- }
- else {
- printf("delete fail!!\n");
- }
- }
- return head;
- }
- struct student* add(struct student* head, struct student* add_node) {
- if (head == NULL) {
- return add_node;
- }
- if (head->num > add_node->num) {
- add_node->next = head;
- return add_node;
- }
- struct student* q, * p;
- q = head;
- p = head->next;
- while (p->num < add_node->num&&p->next!=NULL) {
- q = p;
- p = p->next;
- }
- if (p->num > add_node->num) {
- q->next = add_node;
- add_node->next = p;
- }
- else {
- p->next = add_node;
- }
- return head;
- }
- struct student* search(struct student* head, int search_num) {
- struct student * p = head;
- if (head == NULL) {
- return NULL;
- }
- while (p->num != search_num&&p->next!=NULL) {
- p = p->next;
- }
- if (p->num == search_num) {
- return p;
- }
- else {
- return NULL;
- }
- }
- int main() {
- struct student* head, * p;
- head = p = NULL;
- head = p = creat();
- while (p != NULL) {
- printf("num-%d math-%d english-%d\n", p->num, p->scr.math, p->scr.english);
- p = p->next;
- }
- printf("out ending!\n");
- int delete_num;
- printf("please input delete_num:");
- scanf("%d", &delete_num);
- head=delete(head,delete_num);
- struct student* padd_node;
- padd_node = (struct student*)malloc(sizeof(struct student));
- printf("please input add_node num:");
- scanf("%d", &padd_node->num);
- printf("please input add_node math:");
- scanf("%d", &padd_node->scr.math);
- printf("please input add_node english:");
- scanf("%d", &padd_node->scr.english);
- padd_node->next = NULL;
- head = add(head, padd_node);
- p = head;
- while (p != NULL) {
- printf("num-%d math-%d english-%d\n", p->num, p->scr.math, p->scr.english);
- p = p->next;
- }
- printf("out ending!\n");
- struct student* psearch;
- int search_num;
- printf("please input search_num:");
- scanf("%d", &search_num);
- psearch = search(head, search_num);
- if (psearch != NULL) {
- printf("num-%d math-%d english-%d\n", psearch->num, psearch->scr.math, psearch->scr.english);
- }
- else {
- printf("search error!!\n");
- }
- return 0;
- }
-
复制代码- #define _CRT_SECURE_NO_WARNINGS // 必须放在第一行!
- #include<stdio.h>
- #include<stdlib.h>
- int n = 0;
- struct score {
- int math;
- int english;
- };
- struct student {
- int num;
- char name[10];
- struct score scr;
- struct student* next;
- };
- struct student* creat() {
- struct student* head, * tail, * p;
- head = tail = p = NULL;
- while (1) {
- //创建结点并初始化
- p = (struct student*)malloc(sizeof(struct student));
- printf("please input num:");
- scanf("%d", &p->num);
- printf("please input name:");
- scanf("%s", p->name);
- printf("please input math:");
- scanf("%d", &p->scr.math);
- printf("please input english:");
- scanf("%d", &p->scr.english);
- p->next = NULL;
- //判断是否是结束结点(判断输入的num是不是0)
- if (p->num == 0) {
- return head;
- }
- //不是结束结点
- n++;
- //判断是不是头节点
- if (n == 1) {
- head = tail = p;
- }
- else {
- tail->next = p;
- tail = p;
- }
- }
- }
- void print(struct student* head) {
- struct student* p = head;
- while (p != NULL) {
- printf("num-%d\tname-%s\tmath-%d\tenglish-%d\n", p->num, p->name, p->scr.math, p->scr.english);
- p = p->next;
- }
- }
- struct student* search(struct student* head, int search_num) {
- if (head == NULL) {
- return NULL;
- }
- struct student* p = head;
- while (p->num != search_num && p->next != NULL) {
- p = p->next;
- }
- if (p->num == search_num) {
- return p;
- }
- else {
- return NULL;
- }
- }
- struct student* add(struct student* head, struct student* add_node) {
- if (head == NULL) {//空链表
- return add_node;
- }
- if (head->num > add_node->num) {//插到头结点
- add_node->next = head;
- return add_node;
- }
- struct student* q, * p;
- q = head;
- p = head->next;
- if (p == NULL) {
- head->next = add_node;
- return head;
- }
- while (p->num < add_node->num&&p->next!=NULL) {//中间结点和尾结点
- q = p;
- p = p->next;
- }
- if (p->num == add_node->num) {
- printf("add_node repeat!\n");
- return head;
- }
- if (p->num > add_node->num) {//此判断说明插入链表中间节点
- q->next = add_node;
- add_node->next = p;
- }
- else {//此判断说明插入链表尾节点
- p->next = add_node;
- }
-
- return head;
- }
- struct student* delete(struct student* head, int delete_num) {
- if (head == NULL) {
- printf("delete error!\n");
- return head;
- }
- if (head->num == delete_num) {
- printf("delete success\n");
- return head->next;
- }
- struct student* q, * p;
- q = head;
- p = head->next;
- if (p == NULL) {
- printf("delete error!\n");
- return head;
- }
- while (p->num != delete_num && p->next != NULL) {
- q = p;
- p = p->next;
- }
- if (p->num == delete_num) {
- q->next = p->next;
- printf("delete success\n");
- return head;
- }
- else {
- printf("delete error!\n");
- return head;
- }
- }
- int main() {
- struct student* head, *search_node,*add_node;
- int search_num, delete_num;
- head = creat();
- print(head);
- add_node = (struct student*)malloc(sizeof(struct student));
- printf("please input add_node num:");
- scanf("%d", &add_node->num);
- printf("please input add_node name:");
- scanf("%s", add_node->name);
- printf("please input add_node math:");
- scanf("%d", &add_node->scr.math);
- printf("please input add_node english:");
- scanf("%d", &add_node->scr.english);
- add_node->next = NULL;
- head = add(head, add_node);
- print(head);
- printf("please input delete_num:");
- scanf("%d", &delete_num);
- head = delete(head, delete_num);
- print(head);
- printf("please input search_num:");
- scanf("%d", &search_num);
- search_node = search(head,search_num);
- if (search_node == NULL) {
- printf("search erroe!\n");
- }
- else {
- printf("num-%d\tname-%s\tmath-%d\tenglish-%d\n", search_node->num, search_node->name, search_node->scr.math, search_node->scr.english);
- }
- return 0;
- }
复制代码
2.3: typedef
用typedef声明新的类型名来代替已有的类型名
2.3.1:用法1(一般数据类型): - typedef int III;
- int main() {
-
- III iii = 10;
- printf("%d", iii);
- return 0;
-
- }
复制代码
2.3.2:用法2(定义结构体类型): - typedef struct {
- int year;
- int month;
- int day;
- }DATA;
- DATA birthday;
- birthday.year = 2001;
- birthday.month = 06;
- birthday.day =8;
- printf("year-%d,month-%d,day-%d", birthday.year, birthday.month, birthday.day);
复制代码
typedef 定义结构体
- 语法 :在定义结构体的同时,使用 typedef 为其创建一个别名,这样在后续声明变量时就可以直接使用这个别名,而不需要再写 struct 关键字。
2.3.3:用法3(定义为数组类型) - typedef int NUM[100];
- NUM num = { 0 };
- printf("%d\n", sizeof(num));
-
-
- typedef char* p;
- p p1= "hello";
- printf("%s\n", p1);
-
-
-
- typedef int (*p)(int,int);
- int fun(int a, int b) {
- return a + b;
- }
- p p1;
- p1 = fun;
- printf("sum=%d\n", p1(1, 2));
复制代码
三、补充知识
在 C 语言中,数据的进制表示主要通过特定的前缀来区分,以下是常见进制及其前缀的介绍:
十进制(Decimal)
- 前缀特点 :没有特殊前缀,数字直接按正常方式书写即可,比如 123、456 等,都是十进制数。
- 适用场景 :日常编程中,十进制是最常用的表示方式,适用于各种整数和小数的表示,比如变量赋值、数学运算等。
八进制(Octal)
- 前缀特点 :以数字 0(零)开头,例如 0123、0456 等。需要注意的是,这里的 0 是阿拉伯数字零,不是字母 O。
- 适用场景 :八进制在某些特定场景下比较有用,比如文件权限设置(如 Unix/Linux 系统中的文件权限),用八进制表示权限更简洁直观。在编程中,如果需要将整数以八进制形式输出或处理,可以使用八进制前缀。
十六进制(Hexadecimal)
- 前缀特点 :以 0x 或 0X 开头,例如 0x1A2B、0XABCDEF 等。十六进制数中可以用字母 A-F(不区分大小写)来表示数值 10-15。
- 适用场景 :十六进制常用于表示内存地址、颜色值(如 HTML/CSS 中的颜色代码)、位操作等场景。因为十六进制和二进制的转换比较方便,每一位十六进制数对应 4 位二进制数,在处理低层数据或硬件相关编程时也很常用。
二进制(Binary)
- 前缀特点 :在标准 C 语言中,没有官方规定的二进制前缀。但在一些编译器(如 GCC)支持的扩展语法中,可以用 0b 或 0B 作为前缀来表示二进制数,例如 0b1010、0B1101 等。
- 适用场景 :二进制主要用于底层编程、位操作相关的场景,如设置硬件寄存器、处理二进制文件等。虽然标准 C 没有二进制前缀,但在实际编程中,如果编译器支持,使用二进制前缀可以让代码更直观易懂。
|