目录
指针
1 指针
通过指针能找到以指针为地址的的内存单元。
编号=地址=指针
比如说:你要找你朋友玩,你需要她家的地址(指针),才能找到她(数据),和她家(数据所占字节),然后去具体的房间找她(内存单元)。而你朋友搬家的话,地址是可能改变的(指针变量),随着年龄的不同,你朋友也不同(给指针变量赋值)。
总结:
1)指针就是变量,用来存放地址的变量。(存放在指针中的值都被当做地址来处理。)
2)指针用来存放地址,地址是唯一标示一块地址空间的。
3)指针的大小在32位平台是4个字节,在64位平台是8个字节。
1.1 指针和指针类型
1)指针类型的意义
指针类型决定了:
a.指针解引用的权限有多大
b.指针走一步走多远(步长),比如说int走4个内存单元,char走一个内存单元
1.2 野指针
1)概念:指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
2)成因:
a.指针未初始化
举例:int* p; *p = 20;
造成了非法访问内存
b.指针越界访问
c.指针指向的空间释放
3)如何规避野指针
a.指针初始化
方法一:int* p = NULL; //当不知道初始化什么的时候(包含在头文件#include<stdio.h>中)
方法二:明确知道初始化的值
b.小心指针越界(C语言本身不会检测数组越界行为)
c.指针指向空间是释放及时置空
d.指针使用之前检查有效性
当使用int* p = NULL;时,也会出现问题,空指针不是分配给我们用户的,所以需要检查空指针,如下:
int* p = NULL;
if (p != NULL)
{
*p = 10;
}
1.3 指针运算
1)指针+-整数
举例:*ap++ = 0;
2)指针-指针
举例:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", &arr[9] - &arr[0]);
结果:9
这个例子还说明:指针-指针=两个指针之间元素的个数。
也就是说可以使用指针计算整个数组元素个数。(其他两种方法:a.计数器 b.递归)
前提:两个指针指向同一块空间。
3)指针的关系运算
for(vp = &values[N_VALUES]; vp > &values[0];)
{
*--vp = 0;
}
如果将代码简化如下:
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
*vp = 0;
}
应该避免这样写,因为标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与 指向第一个元素之前的那个内存位置的指针进行比较。
1.4 指针和数组
1)数组名是数组首元素的地址。
2)补充:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr;
//[]是一个操作符 2和arr是两个操作数
//相当于a+b=b+a,这种的交换律
//推导逻辑:
//arr[2]-->*(arr+2)-->*(2+arr)-->2arr[]
//p[2]<==>arr[2]<==>*(arr+2)<==>*(p+2)<==>*(2+p)<==>*(2+arr)<==>2[arr]
return 0;
}