“C语言部分-Day07”
一、命令行参数
给程序传递参数,以main函数为例子
以上代码的执行结果:
默认调用1个参数,即程序本身,因此默认argc的个数为1,argv为程序本身
注意事项:
如何在VS中给程序加参数?
【项目】–【属性】–【调试】–【命令参数】
设置之后的运行结果:
二、结构体(※※※)
C语言的结构体,相当于其它高级语言中的类,但是C语言只能在结构体中定义数据,不能定义方法。
如表示一个学生:
使用结构体创建对象:
2.1 结构体的内存布局
以上面的学生数据结构为例,它在内存中的存储布局如下:
为何占用44字节空间,而不是42字节?
- 多出来的
[...]
是填充的padding
,用于对齐 —- 方便早期CPU寻址
- 因为number + name + gender = 30,而后面的chinese是4,为方便对齐,前面需要是4的倍数,因此+2
2.2 结构体对象的初始化
结构体的初始化方式:
对结构体的操作
注意事项:
2.3 结构体取别名
如2.1中定义的结构体,当我们使用它时,每次都需要在前面加上struct
标识,比较麻烦:
这时候,我们可以用typedef
给该结构体取个别名,使用起来会方便一些
再使用结构体:
还能再精简
三、枚举
3.1 枚举类型的使用
以扑克牌花色为例,如果使用宏定义,代码如下:
改用枚举的代码如下:
3.2 使用typdedef取别名
简化枚举的使用
注意事项:
枚举类型的值,本质上都是一些整数,默认从0开始,可以手动指定
如果混合使用,下一个元素的值默认为上一个元素的值+1,案例如下:
四、指针的高级应用
4.1 动态内存分配
所谓动态内存分配即是在堆上分配内存,它在C语言中有举足轻重的地位,因为它是链式结构的基础。在头文件stdlib.h
中定义有三个动态内存分配的函数,分别是:
4.1.1 malloc的使用
定义:
作用:
- 分配size个字节的内存空间
- 内存块不会清零
- 若分配不成功,返回空指针
使用案例:
4.1.2 calloc的使用
定义:
作用:
- 为num个元素分配内存空间,每个元素的大小为size字节
- 对内存块清零
- 若分配不成功,返回空指针
使用案例:
4.1.3 realloc的使用
定义:
作用:
- 调整先前分配的内存块的大小
- 如分配成功,返回新内存的地址
- 分配失败,返回空指针
注意:ptr应指向的先前使用动态内存函数分配的内存块
使用案例:
4.1.4 空指针的概念
不指向任何对象的指针,称为空指针,用宏NULL表示,其值为0
4.1.5 案例
编写一个函数,把两个字符串拼接起来,且不改变其中任何一个字符串
4.2 释放内存空间
4.2.1 内存泄漏的问题
如果动态申请的内存没有被释放,则会产生内存泄漏的问题,如以下代码:
图示为:
长时间的内存泄漏,容易造成out of memory
的问题。如何释放内存呢?需要使用到free函数。
定义:
案例:
Q1:ptr只是指向申请内存块的首地址,那么free函数是如何知道该释放多大的内存?
因为实际申请的内存空间会稍大一些,里面自带关键信息,比如:
4.2.2 悬空指针的问题
使用free函数可以避免内存泄漏的问题,但是会引用新的问题:悬空指针,即某指针指向一片内存空间,但是该空间已经被释放,代码如下:
图示:
注意事项:
悬空指针的问题非常难发现,因此使用的时候需注意
4.3 链表
用一条链,将所有节点串联
4.3.1 结点
链表结点分为:
定义结点代码:
4.3.2 链表分类
分类如下:
循环链表在实际生产中用的比较少,但是在处理环状数据的时候特别有用,像约瑟夫环
4.3.3 单向链表案例
如何实现一个单向链表:
4.4 二级指针
二级指针,即指向指针的指针,其定义方式如下:
常用于在函数中修改指针变量的值,比如
4.5 函数指针
即指向函数的指针 (函数也有地址)
案例如下:
4.6 qsort函数
可以对任意类型的数组进行排序(不管元素类型是什么)
排序的目的是什么?
qsort函数的定义:
案例:给student结构体数组排序