前言:本篇是详解指针(1),内容包括:指针是什么,指针和指针类型,野指针
part 1:指针是什么
1 指针就是地址,口语中说的指针通常指的是指针变量
2 指针变量:存放地址的变量
我们使用&(取地址操作符)取出变量在内存中的起始地址,将其存入指针变量中
举例:
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a;
return 0;
}
变量a在内存中开辟一块空间用于存放数字10
&a:取出变量a的地址存入指针变量p中
a是int类型,在内存中占4个字节的空间,&a是取出a的4个字节中的第一个字节的地址
int*p 解读: *表示p是一个指针,int 表示指针变量p所指向的类型是int
3 指针的大小
指针的大小在32位平台上是4个字节,在64位平台是8个字节
part 2:指针和指针类型
指针的定义方式:类型+*
char*pc=NULL;//存放char类型变量的地址
int*pi=NULL;//存放int类型变量的地址
short*ps=NULL;//存放short类型变量的地址
long*pl=NULL;//存放long类型变量的地址
float*pf=NULL;//存放float类型变量的地址
double*pb=NULL;//存放double类型变量的地址
指针类型的意义:
1.指针+-整数:指针的类型决定了指针向前或向后走一步有多大(步长)
举例:
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc+1);
printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
定义了字符型指针pc,整型指针pi
将整型变量n的地址存储到指针变量pc和pi中
%p:打印地址
我们可以看到:pc和pi中都存储了整型变量n,4个字节的第一个字节的地址:006FFDF0
pc+1:006FFDF1
由于pc是char*类型的指针,故pc+1能够跳过一个char类型,即跳过一个字节,故而pc+1指向了n的4个字节中的第二个字节
pi+1:006FFDF4
由于pi是int*类型的指针,故pi+1能够跳过一个int类型,即跳过4个字节,故而pi+1指向了紧挨着n的那块空间的第一个字节
2.指针的解引用:指针的类型决定了对指针解引用的时候有多大的权限(能够操作几个字节)
比如: char* 的指针解引用只能访问一个字节,而 int* 的指针的解引用就能访问四个字节
举例:
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0;
*pi = 0;
return 0;
}
变量n存储一个十六进制的数字:0x11223344,刚好占用4个字节的空间
因为一个十六进制数字的一位对应二进制的四个比特位,即十六进制数字的两位对应二进制的8个比特位,即1个字节
:变量n开辟一块空间存储此数字
char*类型的指针pc和int*类型的指针pi都存储了n的地址
对指针变量pc和pi解引用(*pc,*pi)就能够对n进行修改(即修改变量n中存储的数字)
:指针pc中存储了变量n的地址:0xFBF9AC
:指针pi中存储了变量n的地址:0xFBF9AC
:*pc:对char*类型的指针pc解引用,只能够访问一个字节的空间(操作修改一个字节),故而修改了变量n中的第一个字节,使之变为0
:*pi 对int*类型的指针pi解引用,能够访问4个字节的空间(操作修改4个字节),故而修改了n变量中的全部四个字节,使之全部变为0
part 3:野指针
概念:野指针即指针指向的空间是不可知的(随机的,不正确的)
1. 野指针成因
a. 指针未初始化
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
指针p中存储的一块空间地址是随机的,对一块不是自己的空间进行修改是非法的
b. 指针越界访问
举例:
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i <= 11; i++)
{
*(p++) = i;
}
return 0;
}
这是arr数组开辟的存放10个整型的空间
使用整型指针p对数组中的内容进行赋值,0~9
此时arr数组申请的10个整型的空间已经访问结束,但是i还在++
指针变量p此时会发生越界访问,将不属于arr数组开辟的空间内容进行修改赋值
此时的p就是野指针,p超出了arr数组的范围
c. 指针指向的空间释放
比如
2 如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放,及时置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
指针初始化:
若是指针有明确指向,则初始化为确切的地址
int main()
{
int a = 10;
int* p = &a;
return 0;
}
若是指针没有明确指向,则初始化为空指针NULL
int *p = NULL;
检查指针有效性:
if(p != NULL)
{
*p = 20;
}
若是指针不为空指针NULL,则对指针进行操作