在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
假设内存块为一栋大楼,每个内存单元为一间房子,每个指针就好比每间房子的门牌号,我们通过门牌号找到相应的房子,同理,我们可以通过指针找到相应的内存单元。
#include
int main()
{
int a = 10;
printf("%d\n",a);//在内存中开辟一块空间
int *p = &a;//这里我们对变量a,取出它的地址,可以使用&操作符。
//**将a的地址存放在p变量中,p就是一个之指针变量**。
*p=2;//*+指针表示解引用,相当于通过指针找到a这块内存单元
printf("%d\n",a);
return 0;
}
在32位机器上,指针总是由32个0或1组成,所以指针的大小为8个4个字节,因为每个0或1为一个比特为(bit),每8个比特位为一个字节。
例如:11111111 00000000 00001111 00110011 这是一个指针在32位机器在内存中存储的样子
同理,在64位机器中,指针的大小为8个字节
在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所
以一个指针变量的大小就应该是4个字节
变量的都有类型,整形和浮点型等,同样指针也有类型。
指针的定义方式是: type + * 。 其实: char* 类型的指针是为了存放 char 类型变量的地址。 short* 类型的指针是为了存放 short 类型变量的地址。 int* 类型的指针是为了存放int 类型变量的地址。
指针的类型的意义是什么呢?
那么,我们来看下列代码及其运行结果:
int main()
{
int i = 0;
int *pa = &i;
char*pc = (char*)&i;
printf("%p\n", pa);//%p是打印地址
printf("%p\n", pa + 1);
printf("--------------\n");
printf("%p\n", pc);
printf("%p\n", pc + 1);
return 0;
}
得到的结果如上图所示,将i的地址存储在指针intpa,然后将i的地址强制转换为char存储在指针pc中,首先打印出来的pa和pc的地址都相同,但将pa和pc各自+1,pa移动了4个字节,pc移动了一个字节。
接下来我们在看一块代码
int main()
{
int a = 0x11223344;
int *pa = &a;
char *pc = (char*)&a;
*pc = 0;
//通过指针pc访问a,只访问一个字节
//通过指针pa访问,访问了4个字节
*pa = 0;
return 0;
}
我们先将这块代码进行调试,打开内存,然后把指针pc输进去
我们可以看到44 33 22 11 分别各自占一个字节存储在在内存中;在进行调试,如下图:
可见,当我们调试*pc(p表示的是指针的解引用,意思通过指针找到a这块空间)后,内存中只改变一个了字节,接下来,我们在进行调试
调试pa后,内存中4个字节都变为0;(指针pa和pc存的都是a的地址,它们指向的内存都为i,只是指针pa为int型,指针pc为char型)
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
int main()
{
int a;
int* pa = &a;
return 0;
}
这里的局部变量指针未初始化,默认为随机值,因为a没有初始化的值,所以指针pa指向的内容是随机的,所以指针pa为野指针`
int main()
{
int arr[10] = 0;
int *pa = arr;
for (int i = 0; i <= 11; i++)
{
*(pa + 1) = 0;
}
//当指针p超出数组arr的范围时,p就是野指针
return 0;
}
因为数组arr初始化为10个元素,但指针*(pa+10)和*(pa+11)在加的过程中超过了数组arr的范围,这两个指针不知到指向哪里,为随机值,所以为野指针。
#include
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}