前言:指针是C语言中一个重要概念,也是C语言的一个重要特色。正确灵活的运用它,可以使程序简洁、高效,我们要深入学习和掌握指针。指针个概念比较复杂,使用时也比较灵活,所以我们在学习时要多思考,多练习,在实践中掌握它。接下来就让我们进入指针的学习。
一、指针是什么
想要弄清楚指针,必须先弄清楚数据在内存中是如何存储的,又是如何读取的。
如果在程序中定义一个变量,在对程序编译时,系统会给变量分配内存单元,编译系统会根据定义的变量类型,分配一定长度的空间。例如:为整型变量提供4个字节空间,为字符变量提供一个字节空间。
将内存分成一个一个小的单元,每个单元是一个字节,每一个字节都有一个编号,这就是“地址”
我们可以换一种理解方法,地址就相当于旅馆中的房间号,地址所标志的内存单元中存放的数据相当于旅馆房间中住的客人。例如:房间门口挂一个房间号2008,这个2008就是房间的地址,或者说2008指向该房间。因此,地址形象化为“指针”,意思就是通过它可以找到以它为地址的内存单元。
说明:我们对存储单元进行访问,我们除了要位置信息外,还要该数据的类型信息(例如:整形和单精度浮点型都是4个字节,但存储的方式不同),只有数据地址信息,而没有类型信息是无法对该数据进行存取的。
总结:指针就是地址,口语中说的指针通常指的是指针变量。
指针的大小在32位平台是4个字节,在64位平台是8个字节。
#include <stdio.h> int main() { int a = 10; //在内存中开辟一块空间 int* p = &a; //这里我们对变量a,取出它的地址,可以使用&操作符。 //a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个之指针变量。 //int* 是指针变量p的类型 return 0; }
如果有一个变量专门存放另一个变量的地址(即指针),则称他为“指针变量”。上面p就是一个指针变量。指针变量就是地址变量,用来存放地址,指针变量的值就是地址(即指针)。
注意:区分“指针”和“指针变量”这两个概念。例如,可以说变量i的指针(即地址)是2000,而不能说i的指针变量是2000,指针是一个地址,而指针变量是存放地址的变量。
二、指针变量
怎么定义指针变量
类型名* 指针变量名
说明:在定义指针变量时要注意
(1).指针变量前面的“*”表示该变量为指针变量。
(2).在定义指针变量时必须指定基类型。一个变量的指针的含义包括两个方面,一是以存储单元编号表示的纯地址,一是它指向的存储单元的数据类型。
三、指针和指针类型
所有类型的指针大小都相同,为什么不用一个相同的类型呢?我们通过指针类型的意义,来解答这个疑问
指针类型的意义
int*的指针解引用访问4个字节
char*的指针解引用访问一个字节
结论:指针类型可以决定指针解引用的时候访问几个字节(指针的权限)
指针类型决定了指针+1操作时跳过的字节
整形指针跳过4个字节
字符指针跳过1个字节
四、野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
4.1野指针的成因
1.指针未初始化
1. #include <stdio.h> 2. int main() 3. { 4. int *p;//局部变量指针未初始化,默认为随机值 5. *p = 20; 6. return 0; 7. }
2.指针越界访问
#include <stdio.h> int main() { int arr[10] = {0}; int *p = arr; int i = 0; for(i=0; i<=11; i++) { //当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i; } return 0; }
3.指针指向的空间释放
#include <stdio.h> int* test() { int a = 100; return &a; } int main() { int* p = test(); printf("%d\n", *p); return 0; }
野指针就像大街上的野狗,是危险的,那在我们编程中怎样避免写出野指针呢?
4.2如何规避野指针
1. 指针初始化
- 明确知道指针应该初始化为谁的指针,就直接初始化
- 不知道指针初始化为什么值,暂时初始化为NULL
#include <stdio.h> int main() { int a = 10; int* p = &a; int* ptr = NULL; return 0; }
C++中NULL就是数字0
C语言中是将0强制转化为void* --本质还是0
2. 小心指针越界
3. 指针指向的空间释放,及时置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性