目录
3.指针变量不再使用时,及时置NULL,指针使⽤之前检查有效性
1.指针变量的大小
指针变量的大小取决于地址的大小
32位平台下地址是32个bit位(即4个字节)
64位平台下地址是64个bit位(即8个字节)
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(double*));
return 0;
}
既然指针大小与指针类型无关,那为什么要有各种各样的指针类型呢?接着看下去
2.指针的解引用
#include <stdio.h>
int main()
{
int n = 0x11223344;
int* pi = &n;//char* pc = (char*)&n;
*pi = 0;//*pc = 0;
return 0;
}
左边:
右边:
调试我们可以看到,左边将n的4个字节全部改为0,但是右边只是将n的第⼀个字节改为0。
结论:指针的类型决定了,对指针解引⽤的时候有多大的权限(⼀次能操作几个字节)。
3.指针+-整数
#include <stdio.h>
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;
}
代码运⾏的结果如下:
我们可以看出, char* 类型的指针变量+1跳过1个字节, int* 类型的指针变量+1跳过了4个字节。 这就是指针变量的类型差异带来的变化。
结论:指针的类型决定了指针向前或者向后走一步有多大(距离)。
4.void*指针
在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为无具体类型的指针(或者叫泛型指 针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引⽤的运算。
5.const修饰指针变量
const int* p = NULL;//(也可以写成int const* p)const右边是*p,所以*p不能变,但p可以变
int* const p = NULL;//const右边是p,所以p不能变,但*p可以变
6.指针运算
6.1指针+-整数
*(p+i) = p[i]//可以认为[]有解引用的作用
6.2指针+-指针
前提:都指向同一块空间
指针+-指针 = 两个指针之间的元素个数
p1 p1+9 9个元素
7.野指针
7.1野指针成因
7.1.1指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
7.1.2指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = &arr[0];
int i = 0;
for(i=0; i<=11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
7.1.3指针指向的空间释放
#include <stdio.h>
int* test()
{
int n = 100;
return &n;
}
int main()
{
int*p = test();
printf("%d\n", *p);
return 0;
}
7.2如何规避野指针
7.2.1指针初始化
指针初始化 如果明确知道指针指向哪里就直接赋值地址,如果不知道指针应该指向哪里,可以给指针赋值NULL. NULL 是C语言中定义的⼀个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错。
7.2.2小心指针越界
⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是越界访问。
7.2.3指针变量不再使用时,及时置NULL,指针使用之前检查有效性
当指针变量指向⼀块区域的时候,我们可以通过指针访问该区域,后期不再使⽤这个指针访问空间的 时候,我们可以把该指针置为NULL。因为约定俗成的⼀个规则就是:只要是NULL指针就不去访问, 同时使⽤指针之前可以判断指针是否为NULL。
7.2.4避免返回局部变量的地址
如造成野指针的第3个例⼦(7.1.3指针指向的空间释放),不要返回局部变量的地址
8.assert断言
assert.h 头⽂件定义了宏 assert() ,⽤于在运行时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断言”。
如:assert(p != NULL);
#define NDEBUG//写了这个就会注释掉assert
#include <assert.h>
以上有问题,还请大佬指点