一、指针是什么?
如何管理内存呢?其实是分成一个一个的单元,每个内存单元大小位1bety,我们把内存单元的编号成为地址,也就是指针。
总之:指针就是地址,口语中指针通常指的是指针变量。
指针的大小,跟环境有关,x86环境下是4字节,x64环境下是8byte。
二、指针类型决定什么?
1、指针类型的差异,决定不了指针的大小,能决定其访问字节个数
未改变a的值时,a的内存中存储为0x00CFFE04 所示 👆
通过int *的指针变量改变a的值时如下👇,四个字节都被改变
当通过char*型变量再进行改变时,只改变了一个字节👇
pa是int*型,所以能访问4byte,而ca是char*型,只能访问1byte 。
2、决定指针+-整数操作时,跳过的字节个数(指针步长)
int*型 +1 跳4个字节 char*型 +1 跳 1个字节
3、int*和float*虽然指针步长一样,访问字节也一样,但是,不通用。
二、野指针
1、指针没有初始化
2、越界访问
3、指针指向的空间释放(比如,函数)
总之就是,指针指向了,不是我们当前要用的空间。像一条没有栓链子的狼。
好习惯:
1、初始化(NULL)
2、小心越界
3、避免返回局部变量地址
4、空间释放的时候及时给指针赋予NULL
三、指针运算
1、指针 + - 整数
前面已经介绍了,+一个整数,相当于往后跳一个指针类型的步长
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*p = i;
p++;
}
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
//0 1 2 3 4 5 6 7 8 9
return 0;
}
注意:*(p++)和(*p)++ 是不一样的哦,前者是*p,p++,变得指的地址;后者是对指针变量p所指向的对象++
2、指针 - 指针
得到的是 俩指针间的元素个数
使用条件:必须指的是同一个数组,有关系
比如:int arr[10]={0}; &arr[5] - &arr[0] = 5
利用指针-指针,求字符串长度 👇
int my_strlen(char* p)
{
char* star = p;
while (*p != '\0')
{
p++;
}
return (p-star);
}
int main()
{
char arr[] = "abcde";
//自定义函数求字符串长度
int len=my_strlen(arr);
printf("%d\n", len);
return 0;
}
3、指针的关系运算
可以比较大小
int main()
{
int arr[5] = { 0 };
int* vp=NULL;
int i = 0;
for (vp = &arr[5]; vp > &arr[0];)
{
*--vp = 1;
}
for (i = 0; i < 5; i++)
{
printf("%d ", arr[i]);
}
// 1 1 1 1 1
}
四、二级指针
举例说明:
int a=10;
int* pa=&a; //pa是指针变量,一级指针
int* *ppa=&pa; //ppa是二级指针,它里面放的是指针变量pa的地址
**ppa=20; //通过*ppa找到pa,再*找到a
a=20;
五、指针数组
存放指针的数组
int main()
{
int c = 10;
int b = 20;
int a = 99;
int d = 55;
//假如不用数组,麻烦!!!
int* pc = &c;
int* pb = &b;
int* pa = &a;
int* pd = &d;
//用数组^>^
int* arr[4] = { &a,&b,&c,&d };
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d " ,* arr[i]);
}
//99 20 10 55
return 0;
}
arr就是指针数组
补充:其实数组和指针有一定的关系,对于数组brr brr[i] <==> *(arr+i)