1. 函数相关
1.1 return 和 exit 的区别
return
主函数(main)
,程序结束return
其它函数,程序不结束exit()
函数,会结束整个程序,也就是结束进程
1.2 分文件编程
同一个文件如何防止文件重复包含(包含多次,只有一次生效):
方法1:
#pragma once
方法2:
#ifndef _XXXX_H
#define _XXXX_H
//函数声明
#endif /*_XXXX_H*/
2. 指针相关概念
2.1 野指针:
表示这个指针变量保存了一个没有意义(非法)的地址
举例1:
以上程序运行到第23行时会报错,因为我们对野指针进行了操作,首先明确:
- 只有定义后的变量,此变量的地址才是合法地址
- 野指针就是保存没有意义地址的指针变量
- 操作野指针变量本身不会有任何问题
- 操作野指针所指向的内存才导致段错误
程序结构框图如下:
由于上述程序的第23行在对系统未授权的内存进行修改,所以会出现段错误,程序终止报错。
举例2:
程序结构图如下:
程序在第20行会报错,因为定义了一个指针变量但是未给它赋初值,系统会随机给它赋值,如上图所示结构图,它可能是某个未被授权的内存地址:
2.2 空指针:
- 空指针,就是给指针变量赋值为NULL
- NULL就是数字0
- 空指针可以防止对野指针的随意操作
举例1:
初试化变量阶段的结构图:
初始化之后代码运行的结构图如下:
此时在判断条件里确认不是空指针,就能进行操作了。
2.3 指针大小:
- 32位编译器用32位大小(4字节)保存地址
- 64位编译器用64位大小(8字节)保存地址
在64位编译器下,结果都是8个字节:
2.4 多级指针:
- 如果定义一个合适类型的变量保存另一个变量的地址
- 在需要保存变量地址的类型基础上加一个*
举例1:
结构图:
求出以下结果:
举例2:
处理指针问题时遵循如下三点即可:
- 指针变量也是一个变量,是变量就可以赋值
- 指针指向谁,就把谁的地址赋给指针
- *p操作的是指针所指向内存
程序结构图如下:
程序会在运行到第27行时报错,因为p是野指针,没有指向合法内存,操作野指针指向的内存导致段错误。
2.5 [ ]不是数组的专属:
需要注意的是,不能操作p[1]
:
2.6 万能指针:
- 不可以定义void类型的普通变量,不能确定类型
如:void a;
会报错 - 可以定义
void *变量
,void *
指针也叫万能指针 void *
可以指向任何类型的变量,使用指针所指向的内存时,最好转换为它本身的指针类型
需要转换指针类型的原因,如下图,因为p取的是a的地址,它存储的是a的首地址,但此时p的类型是void *
,它在操作*p
的时候不知道需要操作几个字节,也就是不能确定自己的步长是多少,所以转换为int *
,告诉编译器操作内存为多大,所以这里需要转换:
2.7 const 修饰的指针:
情形1:const 修饰 *
情形2:const
修饰指针变量
情形3:const
既修饰 * ,也修饰指针变量,此时两个都不能修改