一.指针含义和类型
指针,就是地址,口语中说的指针通常指的是指针变量。
![](https://i-blog.csdnimg.cn/blog_migrate/67f1c7a1ced126a3cbda4744020497b1.png)
如图,在VS2019中,x86为32位,x64为64位,所以证明了指针的大小只与平台有关。
指针的定义方式是: type + * 也就是指针类型。
指针类型的意义为:
1.指针类型决定了在解引用的是一次能访问几个字节(指针的权限)
2.指针类型决定了指针向前或者向后走一步,走多大距离(单位是字节)
指针 + - 整数
此处验证指针类型意义2
二.野指针
野指针的成因有以下点:
1.指针未初始化
2.指针越界访问
3.指针指向的空间释放
此时*p仍是100,但是在中间加入个printf调动内存的变化后:
此时*p就会变化,因为创建的自定义函数int*test当中的变量a有生命周期,走出这个函数,内存使用权限便改变。再没被调用前仍是原值100。当使用printf函数调动内存改变后,值便随之改变。
所以如何规避野指针?
#include <stdio.h>
int main()
{
int* p = NULL;
}
三.指针运算
1.指针-指针
int my_strlen(char* arr)
{
char* s = arr;
while (*s != '\0')
{
s++;
}
return s - arr;
}
#include <stdio.h>
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
指针-指针得到数组中间元素的个数,又如下:
#include <stdio.h>
int main()
{
char arr[7] = "abcdef";
char* p = arr;
printf("%d\n", &arr[5] - &arr[0]);
printf("%d\n", &arr[0] - &arr[5]);
return 0;
}
&arr[5]==p+5 , &arr[0]==p 所以&arr[5]-&arr[0]=5
2.指针的关系运算
指向第一个元素之前的那个内存位置的指针进行比较。
四.数组与指针
数组名表示的是数组首元素的地址,下图中p+i其实计算的是数组 arr 下标为i的地址
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
/*for (i = 0; i < sz; i++)
{
printf("%p == %p\n", p + i, &arr[i]);
}*/
for (i = 0; i < sz; i++)
{
printf("%d ", p[i]);//p[i] --> *(p+i) --> arr[i]
}
return 0;
}
arr[ i ] 其实也可以写成如上 p[ i ]形式,等价。直接通过指针来访问数组。
二级指针
#include <stdio.h>
int main()
{
int a = 0;
int* pa = &a;
int** ppa = &pa;//ppa为二级指针,存的是pa指针变量的地址
int*** pppa = &ppa;//pppa为三级指针,存的是ppa指针变量的地址
return 0;
}
二级指针,是用来存放指针变量地址
几级函数,解引用时就要用几个 ' * '
指针数组
指针数组 , 就是存放指针的数组
int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr1[5] = { &a, &b, &c };//存放整型指针的数组,里面的每个元素都是整型指针
char d = 'a';
char e = 'b';
char f = 'c';
char* arr2[5] = { &d,&e,&f };//存放字符指针的数组,里面的每个元素都是字符指针
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *(arr1[i]));
}
for (i = 0; i < 3; i++)
{
printf("%c ", *(arr2[i]));
}
return 0;
}
指针数组,是用来存放指针的数组,本质是数组,里面的每个元素都是指针