简单不先于复杂,而是在复杂之后。
目录
1. 指针是什么?
2. 指针和指针类型
2.1 指针+-整数
2.2 指针的解引用
3. 野指针
3.1 野指针成因
3.2 如何规避野指针
1. 指针是什么?
指针理解的两个要点:
1. 指针是内存中最小单元的编号,也就是地址。
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
总结:指针就是地址,口语中说的指针通常是指针变量。
int main() { int a = 10;//a是整型变量,占用4个字节的内存空间 int* pa = &a;//pa是一个指针变量,用来存放地址的 //取地址时取的是第一个字节的地址 return 0; }
总结:
指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理。)
- 一个小的内存单元多大?
---1byte
- 如何编址?
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是1或者0;
那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111
总结:
1. 指针是用来存放地址的,地址是唯一标识一块地址空间的。
2. 指针的大小在32位平台是4个字节,在64位平台是8个字节。
C语言的
%zu
是用来格式化输出size_t
类型数据的格式控制符。size_t是C标准库中定义的一个无符号整型类型,用于表示内存空间大小和数组索引等非负整数值。在C语言中,sizeof操作符用于计算指定类型或表达式的大小(即占用的字节数),并返回一个size_t类型的值。
需要注意的是,
%zu
只能用于格式化输出size_t
类型的值,不能用于其他类型的数据。如果把一个非
size_t
类型的数据使用%zu
格式控制符进行输出,可能会导致输出结果不正确,甚至导致程序崩溃。
2. 指针和指针类型
变量有不同的类型,整型、浮点型等。
指针也有类型。
当有这样的代码:
结论:指针类型决定了指针在被解引用的时候访问几个字节
1. 如果是int*的指针解引用访问4个字节
2. 如果是char*的指针,解引用访问1个字节
在这段代码中,整型指针变量
pa
和字符型指针变量pc
所指向的地址是相同的,即它们都指向变量a
的内存地址。这是因为在C语言中,变量在内存中的存储方式是连续的,而不同类型的指针变量只是指向这些内存地址的方式不同。
在这段代码中,变量
a
在内存中的存储方式是以4个字节为一个单位进行存储,因此它的地址是一个整型地址。当将变量
a
的地址赋给整型指针变量pa
时,pa
所指向的地址与a
的地址是相同的,因为它们都是整型地址。当将变量
a
的地址强制转换为字符型指针类型并赋给字符型指针变量pc
时,pc
所指向的地址也与a
的地址相同,这是因为强制类型转换只改变了指针变量的解释方式,而并没有改变指针变量所指向的地址。因此,虽然整型指针变量和字符型指针变量的类型不同,但它们所指向的地址是相同的。
2.1 指针+-整数
总结:指针的类型决定了指针向前或向后走一步(+1-1操作)有多大,也就是指针的步长。
2.2 指针的解引用
总结:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如:char* 的指针解引用就只能访问一个字节,而int* 的指针解引用就能访问四个字节。
3. 野指针
概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)。
3.1 野指针成因
1. 指针未初始化
int main() { int* p;//没有初始化,就意味着没有明确的指向 //一个局部变量不初始化的话,放的是随机值:0xcccccccc *p = 10;//非法访问内存,这里的p就是野指针 return 0; }
2. 指针越界访问
int main() { int arr[10] = { 0 }; int* p = arr;//&arr[0] int i = 0; for (i = 0; i <= 10; i++) { *p = i; p++; } //当指针指向的范围超出数组arr的范围时,p就是野指针 return 0; }
3. 指针指向的空间释放(动态内存开辟时讲解)
int* test() { int a = 10; return *a; } int main() { int*p = test(); return 0; }
3.2 如何规避野指针
- 指针初始化
- 小心指针越界
- 指针指向空间释放时及时置NULL
- 避免返回局部变量的地址
- 指针使用之前检查有效性
零地址禁止访问,指针没有指向有效空间。
这段代码有一个明显的问题,就是在函数test()中声明的变量a是一个局部变量,在函数执行完毕后将被销毁。
因此,返回该变量的地址是不安全的,因为该地址将指向一块已经被销毁的内存。
这将导致指针变量p所指向的地址变成了一个野指针,可能会引发不可预测的错误,这是一种非常危险的行为。
如果想要正确地使用返回指针,可以考虑使用动态内存分配函数malloc()来分配一块内存,并将变量的值存储在该内存块中,然后返回该内存块的地址。
动态内存分配在之后的博客会有所体现。
这样可以确保返回的地址始终有效,并且可以安全地使用指针变量。文章来源:https://www.toymoban.com/news/detail-415297.html
文章来源地址https://www.toymoban.com/news/detail-415297.html
int main() { int a = 0; int* p = &a; *p = 20; //null -> 0 int* p2 = NULL; *p2 = 100;//err int* p3 = NULL; if (p3 != NULL) { *p3 = 100;//ok } return 0; }
到了这里,关于【C语言】初阶指针(指针及其类型以及野指针)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!