目的在于了解指针的基本概念和一些用法
下面是本阶段导图:
基本概念
int a = 10;
int* p = &a;
指针就是地址,p为指针变量,存放地址的
一个最小的内存单元为一字节
32位机器指针所占内存 4字节
64位机器指针所占内存 8字节
指针类型
1.指针决定访问
指针类型决定了指针解引用访问的字节大小
int* p ;*p能够访问4个字节
char* p;*p能访问1个字节
double* p; *p能够访问8个字节
int main()
{
int arr[10] = { 0 };
char* p = arr;//将int类型的数据赋值给char* 型的指针
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = 1;
}
return 0;
}
调试后打开内存窗口
可以看到,在int类型的数组中,解引用char*后每次访问的都是1个字节,
但若解引用int*型的指针,则每次访问的都是4个字节即图中的每一行
2.指针决定步长
加上一个整数,指针跳过几个字节
int* p; p+1 -> 4
char* p; p+1 -> 1
double* p; p+1 -> 8
int main()
{
int a = 10;
int* pa = &a;
char* pc = &a;
printf("%p\n",pa);
printf("%p\n",pa + 1);//地址跳过4个字节
printf("%p\n",pc);
printf("%p\n",pc + 1);//地址跳过1个字节
return 0;
}
野指针
野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
野指针主要出现在以下三种情况:
未初始化
指针变量初始化时未指向地址
int* p;
*p = 20;
越界
指针越界访问,一般出现在数组中,指针变量实际访问的地址,已经超越数组的范围
int main()
{
int arr[10] = { 0 };
int* pa = arr;
int i = 0;
for (i = 0; i < 11; i++)
{
*(pa++) = i;
//最后一次,指针变量的地址是随机的
}
return 0;
}
空间释放
指针指向的地址已经被释放,一般出现在函数中,main方法中,用指针变量指向的函数返回地址已经被释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
*p = 5;
return 0;
}
当然,在平时需要我们多加注意,避免造成野指针的现象
指针谨记初始化,若暂不初始化,可以赋值NULL
用指针前检验下,可以用assert函数判断
注意:若指针为空时,无法访问它,且无法用其解引用赋值
指针运算
平常运用指针的过程,会涉及到指针的各种运算,常见的数组类的结合会用到
指针+-整数
这里可以参考上面越界中的代码
for (i = 0; i < 11; i++)
{
*(pa++) = i;
//最后一次,指针变量的地址是随机的
}
*pa = i;
pa = pa + 1;
指针- 指针
char ca[5] = {0};
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%d\n",&arr[0] - &arr[9]);
printf("%d\n",&arr[9] - &ca[0]);//err
大指针-小指针得两个元素的中间数:9
同类型减同类型
注意!占空间36,得出来的结果不是36
指针-指针的应用,这里用它实现了strlen的自拟
int my_strlen(char* str)
{
char* start = str;
char* end = str;
while (end != '\0')
//while(*end)
{
end++;
}
//最后一次end会指向'\0'
return end - start;
}
int main()
{
char arr[] = "hello world";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
比大小
将指针间地址进行比较
int main()
{
int arr[5] = { 0 };
int* vp = &arr[0];
for (vp = &arr[0]; vp < &arr[5];)
{
*vp++ = 1;
}
//最后一次,vp指向&arr[5],越界野指针
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d\n", *(arr + i));
}
return 0;
}
在循环中用地址比较
二级指针
指向指针的指针,存放指针的地址。但不仅限于指向指针
int a = 10;
int* pa = &a;
int** ppa = &pa;//二级指针
int*** pppa = &ppa;//三级指针
**ppa = 20;
printf("%d\n",**ppa);
printf("%d\n",a);
理解:
int* pa 相当于int *pa, *pa表示是指针,指向int类型的数据
二级指针int** ppa 相当于int* *ppa,*ppa表示指针,指向int*类型的数据,同理其他。
当然指针还有许多种类,数组指针、指针数组指针、函数指针、函数指针数组指针等,在初级阶段主要把指针的各个概念理解清楚,后面学习各种指针时就会减少许多混淆,困难。