指针
指针在64位机器由64个0到64个1
1. 为什么要指针类型
int main()
{
int a = 0x11223344;
char* p = &a;
*p = 0;
return 0;
}
上面这个代码,我们可以看到,虽然指针在64位系统中都是8字节,char型的指针的确能存下Int类型的地址,但是通过解引用时,int有4个字节,只有低位一个字节被改为0;
所以我们能得到结论1:指针类型决定了指针引用的权限由多大
int main()
{
int n = 10;
char *pc = (char*)&n;//存放n的地址
int *pi = &n;//存放n的地址
printf("%p\n", &n+1); //取地址+1,值加了4个地址
printf("%p\n", pc); //n的地址
printf("%p\n", pc+1); //指针加1,值加了1个地址
printf("%p\n", pi); //n的地址
printf("%p\n", pi+1); //指针加1,值加了4个地址
return 0;
}
上面这个代码,得出的结果是都是指针+1,不同的指针类型加1后的值不同,并不是简单的地址+1,地址+1是得到下一个地址,指针加1要看步数。
提示:我们不是说地址+1就是下一个地址吗?为什么取地址+1加了4个地址,因为在C中,指针+1看指针类型,取地址+1是先按照存放的类型加几个地址的,就比如:char* pp=&n+1,pp仍然是&n+4个地址,因为n是int型
所以我们能得到结论2:指针类型决定了指针每走一步能走多远
2. 野指针
- 1.指针未初始化
- 2.指针超出数组
- 3.指针指向空间释放
int* test(void)//返回一个地址
{
int a = 10;
return &a;
}
int main()
{
int* p = test();//得到a的地址,但是函数已经销毁,不能给你访问了
*p = 20;//强行访问,叫非法访问内存
return 0;
}
- 4.避免野指针 指针初始化(空指针或者有明确目标,包括所有变量都要初始化)
小心指针越界
指针指向空间释放即及时NULL(空指针(void*) 0)
避免返回局部变量的地址
指针使用之前检查有效性
int main()
{
int *p = NULL;
// *p=20; //空指针不会分配给用户,所以不能用,程序卡死
int a = 10;
p = &a;
if(p != NULL)//检查有效性
{
*p = 20;
}
return 0;
}
调试的时候看得特别清楚
3. 指针运算
- 指针±整数
- 指针-指针(指针和指针相加减的前提是同一个指针)+指针没意义
int arr[10] = { 0 };
printf("%d", &arr[9] - &arr[0]);//指针减指针是中间元素的个数
- 指针关系运算
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。看PDF。
4. 指针和数组
- -数组名是数组首元素的地址
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr;//p存放的是数组首元素的地址
p + i = &(arr[i]);
*(p + i) = arr[i];
p = arr;
*(p + 2) = *(arr + 2);
我们要清楚的知道:数组名代表首元素地址,数组名加上[]代表是数据了,就不是地址了