目录
在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向
(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以
说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址
的内存单元。
总的来说,指针就是变量,用来存放地址的变量。
#include <stdio.h>
int main()
{
int a = 10;//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//将a的地址存放在p变量中,p就是一个之指针变量。
return 0; }
那么一个变量单元该是多大呢?
可以知道, 对于 32 位的机器,假设有 32 根地址线,那么假设每根地址线在寻址的是产生一个电信号正电 / 负电( 1 或者0 ),可以控制的内存大小为2^32个单元大小,如果是一个比特位大小,那么能够控制的内存空间为512兆,也就是0.5个g,这显然是不合理的。
因此,一个单元大小是一个字节比较合理,能控制的内存为4g左右。同样,64位的机器更大。
所以,一个指针在32位的情况下,我们就得用4个字节大小才能控制到全部的地址。
当然,在64位系统下,得要8个字节
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
指针的定义方式为:类型+*+名称。
指针的类型与指向的目标的类型一致,指针指向的是目标的地址。
例如:
int a=10;
int* p=&a;
总结: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char* 的
指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
如果我们想要获取指针指向的地址存放的数据,我们就要用到解引用
例如:
int a=10;
int*p =&a;
printf("%d\n",*p);
这样,打印的才是a的值,否则,获取的就是该变量的地址。
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量
在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一
个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。
1、创建指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0; }
2、指针越界访问
#include <stdio.h>
int main()
{
int arr[2] = { 1,2 };
int* p = arr[3];
printf("%d\n", *p);
return 0;
}
当访问超过数组的范围时,p就是野指针。
3、指针的空间释放掉了
那么,如何有效的规避野指针呢?
1、指针初始化
2、小心越界访问
3、指针指向的空间释放
4、使用之前检查有效性
即是将指针置空
int* p = NULL;
#include <stdio.h>
int main()
{
int arr[2] = { 1,2 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
结果:
可以看到,数组名指向的就是第一个元素的地址。
#include <stdio.h>
int main()
{
int arr[2] = { 1,2 };
int* p = arr;
for (int i = 0; i < 2; i++)
{
printf("%d\n", *(p + i));
}
return 0;
}
这里我们可以看出,*(p+i)就是数组下标为i的元素。
实例:
#include <stdio.h>
int main()
{
int arr[2] = { 1,2 };
int* p = arr;
int** p = &p;
return 0;
}
指针指向的是目标变量的地址,那么二级指针指向的就是指针的地址。
同样的,如果要获取指针指向的内容,要使用双重解引用 **