基础知识点 | 1018_指针和引用、野指针,printf函数的实现等知识点
1.指针和引用
定义
指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变
引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量)。
主要区别
- 引用必须被初始化,但是不分配存储空间。指针不声明时初始化,在初始化的时候需要分配存储空间。
- 引用初始化后不能被改变,指针可以改变所指的对象。
- 不存在指向空值的引用,但是存在指向空值的指针。
- “*sizeof* 引用”得到的是所指向的变量(对象)的大小,而“*sizeof* 指针”得到的是指针本身的大小;
传参
-
指针传参
-
本质上是值传递,它传递的是地址指向的值。在值传递的过程中,被调函数的形式参数作为被局部变量进行处理(也就是在栈中开辟了内存空间来存放由主调函数放进来的实参值,从而成为实参的一个副本)。
-
值传递的特点是被调函数对形参的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量。
-
-
引用传递
- 被调函数的形参虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址,被调函数对形参的任何操作都被处理成间接寻址(也就是通过栈中存放的地址访问主调函数中的实参变量)。
- 因此被调函数对形参做的任何操作都影响了主调函数中的实参变量。
注意
如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。
参考来源:
2.free() 和 野指针
一个指针连续被 free() 两次,一定会报错
-
free()
的作用:释放了指针所指向的内存区域,并未修改指针本身的地址值,指针仍指向原来的堆地址。(即,free前后,指针的地址不变)。free()函数只是告诉了操作系统,这块内存我不再使用了,操作系统可以将该块内存重新分配 -
free()
之后发生了什么:该指针变成了一个野指针(野指针指向一个已删除的对象或未申请访问受限内存区域的指针),如果需要再次使用该指针,需要将它置空
野指针
-
野指针是指程序员或操作者不能控制的指针。野指针不是NULL指针,而是指向“垃圾”的指针。
-
造成“野指针”的原因主要有
- 指针变量没有初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。在初始化的时候要么指向合法的指针,要么指向NULL。
- 指针变量被free或delete之后,没有设置为NULL。它们只是把指针所指的内存给释放掉,但并没有把指针本身干掉。通常会用语句if (p != NULL)进行防错处理,然后if语句起不到防错作用,因为即便p不是NULL指针,它也不指向合法的内存块。
- 指针操作超越了变量的作用范围。所以要注意指针的生命周期。
参考来源:
3.printf函数的实现·
printf 函数的函数体:
int printf(const char *fmt, ...)
{
int i;
char buf[256];
// printf参数中的第一个参数地址
va_list arg = (va_list)((char*)(&fmt) + 4);
// 返回要打印出来的字符串长度
i = vsprintf(buf, fmt, arg);
// 将buf中的i个元素的值写到终端中
write(buf, i);
return i;
}
参考来源:
ps.1并不李姐,硬记
1. 字符串除了存放在字符型数组中之外,还可以存放在文字常量区
2. 函数重载是指在 同一作用域内,可以有一组具有 相同函数名,不同参数列表 的函数
重载函数调用的依据是 函数名、参数类型、参数个数
3. 内联函数在编译时是将该函数的目标代码插入每个调用该函数的地方
ps.2值得记录的题
1. 对于下面代码段,正确的赋值语句()
char a[5],*p=a;
B. a="abcd"; // a 是用来标记数组首地址,本身不占运行时程序的空间,是不可修改的左值
C. *p="abcd"; // *p 就是 a[0],无法将字符串赋值给一个字符
- 数组名 是 能隐式转换成指向首元素的指针类型右值,大部分时候可以被看作指向数组首地址的指针。除了以下两种情况
sizeof(a)
的结果并不是4(指针大小),而是5(1字节 * 5
)&a
,可以用一个指针来接受&a的结果
参考来源:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)