指针的定义:
在科学计算中,指针(Pointer)是编程语言的一个对象,利用地址,它的值直接指向(points to)存在电脑 存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的成为“指针”。意思是通过它能找到以它为地址的内存单元。
简言之,指针就是变量,是用来存放地址的变量,存放在指针中的值都被当做地址来处理
地址是唯一标识一块地址空间的
指针的大小:
一个字节占8个比特位(bit),那么,在32位机器上,地址是由32个0或1进行表示,那么就得用4字节来进行存储,所以一个指针变量在32位环境下的大小是4个字节
同理可得,在64位机器上,一个指针变量的大小是8个字节
指针类型
指针是变量,变量有类型,那么指针同样有类型
指针的定义方式为 类型+* ,如下所示:
char *pc = NULL; //存放char类型变量的地址
int *pi = NULL; //存放int类型变量的地址
short *ps = NULL; //存放short类型变量的地址
long *pl=NULL; //存放long类型变量的地址
float *pf = NULL; //存放float类型变量的地址
double *pd = NULL; //存放double类型变量的地址
指针±整数
强调:指针+1,实际是加上其所指向类型的大小
指针解引用(*)
强调:指针在定义时总是占4字节,其定义的类型只能表示其在解引用(*)时可以访问到的字节数3
指针的运算
指针-指针:两个指针相减,表示两指针间所经历的元素的个数(这个元素的类型由两个指针类型所决定(类型必然是相同的,否则无意义))
指针和数组
上述程序中,arr,&arr[0],&arr 三者在数值层面是相同的,但是表示的意义不尽相同,前两个表示整个数组的地址,最后一个表示数组首元素的地址
总结:只有在 sizeof(arr) 和 &arr 这两种情况下数组名才表示整个数组的地址,在其他形式下,皆表示数组首元素的地址,但它们在数值上是相等的
既然可以把数组名当成地址中存放到一个指针中,那么使用指针来访问一个数组就成为了可能
#include<stdio.h>
#include<Windows.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int *p = arr;//指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++){
printf("&arr[%d] = %p <==> p + %d = %p\n", i, &arr[i], i, p + i);
}
system("pause");
return 0;
}
运行结果:
所以(p+i)其实计算的是数组arr下标为i的地址,那我们就可以直接通过指针来访问数组数值:*(p+i)
二级指针
指针变量是变量,是变量就会有地址,有地址就可以进行存储,那么就形成了 二级指针
对于二级指针的运算:
*ppa 通过对ppa中的地址进行解引用,这样找到的是pa , *ppa 其实访问的就是 pa
int b = 20;
*ppa = &b; // <==> pa = &b ;
**ppa 先通过对 *ppa 找到 pa ,然后对 pa 进行解引用操作 :*pa , 则找到的就是a
**ppa = 30;
//等价于 *pa = 30; a = 30;
指针数组
判断一个类型是指针还是数组,由操作符的优先级决定
所以,指针数组是数组,是存放指针的数组