指针是什么
- 指针是内存中一个最小单元的编号,也就是地址
- 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
- 指针就是地址,口语中说的指针通常指的是指针变量。
- 我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量
- 指针的大小在32位平台是4个字节,在64位平台是8个字节
int a = 100;
int * pa = &a; //pa是指针变量,*表示pa是指针变量,int表示pa指向的类型是int
指针和指针类型
指针类型的意义?
- int* 的指针解引用访问4个字节,char* 的指针解引用访问1个字节 结论:指针类型可以决定指针解引用的时候访问多少个字节(指针的权限)
int a = 100; int * pa = &a; //pa是指针变量, //*表示pa是指针变量, //int表示 1.pa指向的类型是int,2.pa解引用的时候访问的对象大小是sizeof(int)
- 指针类型决定指针 +1(-1) 操作时的步长,整型指针+1跳过4个字节,字符指针+1跳过1个字节
野指针
- 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
- 野指针成因:指针未初始化,指针越界访问,指针指向的空间释放
//指针未初始化 int *p;//局部变量指针未初始化,默认为随机值 *p = 20; //指针越界访问 int arr[10] = {0}; int *p = arr; int i = 0; for(i=0; i<=11; i++) { //当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i; }
- 如何规避野指针?
1.指针初始化:明确知道指针应该初始化为谁的地址就直接初始化,不知道指针初始化为什么值就初始化为NULL 2.小心指针越界 3.指针指向的空间释放后,及时置NULL 4.避免返回局部变量的地址 5.指针使用前检查有效性
指针运算
- 指针 +- 整数
int arr[10] = {0}; int* p = &arr[0]; int sz = sizeof arr / sizeof arr[0]; for(int i=0; i<sz; i++) { *p = i; p++; } p = arr; for(int i=0; i<sz; i++) { printf("&d ", *(p+i)); } //*(p+i) == arr[i] //*(arr+i) == arr[i] == *(i+arr) == i[arr]
- 指针 - 指针
int arr[10] = {0}; printf("%d\n", &arr[9] - &arr[0]); //9 //指针 - 指针的绝对值是指针和指针之间的元素个数 //指针和指针相减的前提是两个指针指向了同一块空间
- 指针的关系运算
地址是有大小的,指针的关系运算就是比较指针的大小 标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较, 但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
指针和数组
- 指针
口语指针其实是指针变量,不是数组,指针变量大小是4/8字节,专门用来存放地址
- 数组
数组就是数组,不是指针,数组是一块连续的空间,可以存放1个或多个类型相同的数据
- 指针和数组的联系
数组中,数组名是数组首元素地址,数组名==地址==指针 因为数组是连续存放的,所以通过指针就可以遍历访问整个数组
二级指针
- 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
int a = 10; int* p = &a; //p是一级指针变量,是变量就有地址 int** pp = &p; //pp是二级指针变量,用来存放一级指针变量的地址
指针数组
-
整型数组 - 存放整型的数组 字符数组 - 存放字符的数组 指针数组 - 存放指针(地址)的数组
- 模拟二维数组