一级指针
指针是什么
我们可以把宿舍楼里面的每一个同学看成一个个的变量,存放在一个个宿舍里,而为了方便找到每个同学,我们给每个宿舍标号,而指针就是每个宿舍的门牌号,它的值直接指向地址所对应的变量单元。
为什么要有指针
很明显我们找到一个个同学最快的方式就是通过宿舍门牌号,指针就是为了能找到以它为地址的内存单元。
总结:指针就是地址,指针变量就是变量,用来存放地址的变量(存放在指针里的值都会被当成地址来处理)。注意:一个int型变量占四个字节,每个字节都有一个地址,指针变量存放的是第一个地址。
代码说明:
#incude <stdio.h>
int main()
{
int a=10;
int *p=&a;
return 0;
}
那么在这段代码里,a的地址就是存放在变量p中的,p就是一个指针变量。
指针的大小
指针的大小在32位平台上 是4个字节,在64位平台上是8个字节。
指针的解引用
指针就是它指向的目标
int main()
{
int n = 0x11223344;
char *pc = (char *)&n;
int *pi = &n;
*pc = 0x55;
*pi = 0;
return 0;
}
总结:指针的类型决定对指针解引用的权限。char的指针解引用就只能访问一个字节,而int的指针能访问四个字节。
指针±整数
一句话:指针±1是±其所指元素的类型大小。所以多级指针±1都是±4个字节,因为其所指类型都是指针。
下面来看一段代码:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n = 10;
char *pc = (char *)&n;
int *pi = &n;
printf("%p\n", &n);//1
printf("%p\n", pc);//2
printf("%p\n", pc+1);//3
printf("%p\n", pi);//4
printf("%p\n", pi+1);//5
system("pause");
return 0;
}
这里一共打印了五个变量,1、2、4不做过多解释,我们看到3和5都出现了指针+1,不同的是,3里pc指向的变量类型是char 类型,所以pc+1只+一个字节。而5里pi指向的变量类型是int 型,所以pi+1就+4个字节。
打印结果如下:
指针±指针
代表两个指针之间所经历的的元素个数
举一个例子:
int my_point(int a[10])
{
int *p=&a[0];
int *q=&a[9];
retunr q-p;
}
很明显,这里指针p指向的是下标为0的第一个元素,q指向下标为9的第十个元素,所以q-p就是指针q和指针p之间所经历8的元素个数,为9.
同样,指针之间的运算还可以用来求字符串长度:
int my_strlen(char *a)
{
char *p = a;
while (*p != '\0')
{
p++;
}
return p-a;
}
二级指针
前面我们谈及的都是一级指针,我们知道指针变量也是变量,是变量就有地址,就可以被存放,二级指针就是用来存放指针的地址。
如上图所示,a的地址存放在pa中,pa的地址存放在ppa中,ppa就是一个二级指针。
二级指针解引用
*ppa就是访问pa。
int b=20;
*ppa=&b;//等价于 pa=&b
**ppa=30;
//等价于*pa=30;
//等价于a=30;
指针和数组
指针和数组本身是没有联系的。
数组名的概念
我们先看一段代码。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
system("pause");
return 0;
}
由此可见,数组名和数组首元素的地址是一样的。数组名表示的就是数组首元素的地址。
那么再看下一段代码:
int arr[20]={1,2,3,4,5,6,7,8,9,0};
int *p=arr;
在这里p存放的是首元素的地址。那么我们可以使用指针来访问一个数组。
#include<stdio.h>
#include<stdlib.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]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("&arr[%d]=%p p+%d=%p\n", i, &arr[i], i, p + i);
}
system("pause");
return 0;
}
很明显,&arr[i]和p+i结果是一样的。所以p+i其实计算的是数组的arr下标为i的地址。
那么我们现在直接通过指针来访问数组:
#include<stdio.h>
#include<stdlib.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]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf(" %d", *(p + i));
}
system("pause");
return 0;
}
没有悬念,打印效果如下:
总结
指针也是一个变量,只不过和其他变量不同的原因是:其他变量放值,指针放地址。所以我们不要害怕指针,就和所有的变量一样处理就可以了。