上文我们已经学习了指针的基本概念、内存单元地址的产生,以及指针和指针的类型。这时我们对指针已经有了一个初步的了解,接下来我们将继续深入的学习指针用法。
野指针就是指针指向的位置使不可知的(随机的、不正确的、没有明确限制的)
int main()
{
int* p;
//p没有初始化就意味着没有明确的指向
//一个局部变量不初始化的话,放的是随机值;
//会初始化为一部内容,一般是0xcccccccc这样的值
//这时它就会把0xcccccccc当作是它的地址
//但这个地址所指向的空间不是它的
//也就是说它使用的地址是一个非法的地址
*p = 10;//非法访问内存了,这里的p就是野指针
return 0;
}
int main()
{
int arr[10] = { 0 };
int* p = arr;
for (int i = 0; i <= 10; i++)
{
*p = i;
p++;
}//指针指到前面10个地址的时候还不是野指针
//指针指到第10个地址后面的地址时就是野指针
return 0;
}
int* test()
{
int a = 0;
return &a;
//a会在这里取好一个地址然后返回去
//这时*p的地址就是a所取的这个地址
}
//但是一旦出了test()函数的时候,
//a就会立即销毁这个地址,
//也就是将地址还给了操作系统,
//这时这个空间已经不属于a和p了,
//但是p依然保存着这个地址,
//所以p还能找到这个空间,
//当p再往下执行的时候就是野指针。
int main()
{
int* p = test();
return 0;
}
1.指针初始化
2.小心指针越界
3.避免返回局部变量
4.指针使用之前有效性的检查?
int main()
{
int arr[10] = { 0 };
//arr是首元素的地址
int* p = arr;
//通过指针来访问地址
return 0;
}
//例:给数组初始化
//法一:
#define n 5
int main()
{
float arr[n];
float* a;
for (a = &arr[0]; a < &arr[n];)
{
*a++ = 1;
}
return 0;
}
//法二:
#define n 10
int main()
{
int arr[n] = { 0 };
int* p = arr;
for (int i = 0; i < n; i++)
{
*p = 1;
p++;
}
return 0;
}
补充:*a++?与(*a)++的区别是:前者是给地址++;后者是给指针所指向的对象进行++,比如*a所指向的对象是0,那么(*a)++执行一次后*a所指向的对象就变为1了。
?指针-指针得到绝对值的是指针和指针之间元素的个数,如下图
但不是所有的指针都能相减,只有指向同一块空间的两个指针相减才有意义。例如下面这种。
??
?二级指针是用来存放一级指针变量的地址
int main()
{
int a = 10;
int* pa = &a;//pa是一个一级指针变量
int** pi = &pa;//pi是一个二级指针变量
**pi = 20;
return 0;
}
存放指针的数组其实指针数组,如下图。
使用指针数组模拟二维数组: