一、C语言的本质(操作内存)
二、分配内存的方式
2.1 操作系统在栈区分配
定义变量时,操作系统会根据变量的数据类型分配对应大小的空间。
格式:存储类型 数据类型 变量名
数据类型:
基本类型:char 1字节 %c,%d
short 2字节 %hd
int 4字节 %d
longlong 8字节 %lld
long 32位系统是4字节,64位系统是8字节 %ld
枚举类型
构造类型:数组 结构体 共用体
指针类型:
空类型(void):
2.2 动态内存分配和回收
函数说明:
malloc()
#include <stdlib.h>
void *malloc(size_t size);
功能:在堆区手动分配内存空间
参数:size 要分配的空间的大小 单位:字节
返回值:分配的空间的首地址
free()
#include <stdlib.h>
void free(void *ptr);
功能:释放由malloc在堆区分配的空间
参数:ptr 要释放的空间的首地址
malloc分配的内存是在堆区,堆区的内存空间操作系统不会回收
需要程序员自己记得不用的时候要通过free函数回收资源,否则就会造成内存泄漏(内存只分配,不释放)。
内存泄漏:内存泄漏只发生在长时间运行的程序,如网络的服务器程序上,因为我们自己写的练习的小程序,./a.out 之后进程就直接结束了,进程结束,操作系统会回收进程的所有资源。
三、存储类型
3.1 const
const修饰变量时,表示不能通过变量名来修改变量值。
const 修饰指针的时候
const int *p; 指针p的指向可以变,指向空间的操作内容不能变
int const *p; 指针p的指向可以变,指向空间的操作内容不能变
int * const p; 指针p的指向不可以变,指向空间的操作内容能变
const int * const p; 指针p的指向不可以变,指向空间的操作内容不能变
3.2 static
有两个作用:1、延长局部变量的生命周期至整个程序结束(加了static关键字修饰,相当于修饰成静态变量,静态变量是存储在 data段 或者 bss段的,占用的内存空间是在main函数执行之前就分配的);2、限制作用域(由static修饰的变量只能在当前文件中访问)
3.3extern
作用:声明变量或者函数是在其他的文件中定义的
如果在一个.c文件中想使用另一个.c文件中的变量或者函数
需要在第一个.c中使用关键字 extern 来声明。
static 修饰的变量不能在其他文件中访问
3.4 register
相当于一个寄存器变量,能够提升CPU效率,CPU访问数据优先级(寄存器>cache高速缓存>内存)。register修饰的变量无法获取地址。
3.5 volatile
防止编译器优化的,要求每次取数据的时候都在内存上取,而不是取寄存器或者cache上的数据。
使用场景:多线程访问同一数据;处理中断状态的寄存器时。
3.6 auto
声明变量是一个自动变量,局部变量如果不加修饰,默认是自动变量。
非自动变量:全局变量,static修饰的变量。
四、枚举(数据的有限罗列,防止魔鬼数字)
4.1 定义枚举类型格式:
enum 枚举类型名{ 成员1,成员2, 成员3...成员N};
注意:!!!
1.枚举一旦定义好之后,枚举的成员都是常量
2.枚举的第一个成员如果没有初始值,默认值是 0
3.枚举成员的值是依次递增的,依次加1
4.枚举的成员之间用 逗号 分隔
5.如果给枚举的某个成员赋了初始值,后面成员的值在该值的基础上依次递增1
6.如果枚举的成员和局部变量重名时,采用局部优先原则
7.枚举类型的大小:一般情况下都是 4 ,如果枚举的成员有值超过4字节范围了 就是8
4.2 枚举类型变量的格式:
enum 枚举类型名 变量名;
enum 枚举类型名{ 成员1,成员2, 成员3...成员N}变量1,变量2;
enum { 成员1,成员2, 成员3...成员N}变量1,变量2;(这种情况下,只有这两个变量,无法在定义其他枚举类型变量。)
五、结构体(C语言中结构体里不能封装函数,但是可以有函数指针)
结构体是一个构造类型,里面可以是不同数据类型的集合。结构体的每个成员在内存上是连续的(涉及到内存对齐的问题)。
格式:
struct 结构体名{ 数据类型1 成员1; 数据类型2 成员2; ... 数据类型n 成员n; };
注意事项
1.结构体是一个构造类型
2.结构体的成员是变量
3.结构体的成员之间使用 分号 分隔
4.结构体变量之间可以直接相互赋值
定义结构体变量格式:
struct 结构体名 变量名;
struct 结构体名{ 数据类型1 成员1; 数据类型2 成员2; ... 数据类型n 成员n; }变量1,变量2;
struct { 数据类型1 成员1; 数据类型2 成员2; ... 数据类型n 成员n; }变量1,变量2;
结构体指针:
typedef struct 结构体名{ 数据类型1 成员1; 数据类型2 成员2; ... 数据类型n 成员n; }新的类型名; struct 结构体名 *指针名;
新的类型名 *指针名;
结构体访问成员:
变量.成员; 指针->成员