1.指针运算
上一节中,我们认识了指针类型。指针类型用于保存目标数据对象在内存中的位置。
一个数据对象的内存位置有两个重要信息:
- 数据对象的首地址。
- 数据对象占用存储空间大小。
指针类型通过下面的方式,存储这两个重要信息。
- 指针类型通过值来保存目标数据对象的首地址。
- 类型本身标记目标数据对象的空间大小。
指针类型的值存储的是内存地址。内存地址是从0开始,依次加1的整型数据。
那么,我们自然会产生疑问,既然指针类型的值是整数,它是否能进行运算呢?
2.指针类型与整型进行加减
我们让指针变量从地址100开始加减,看看能不能成功。 如果可以,计算后的结果是什么。
#include <stdio.h>
int main()
{
char* pc;
short* ps;
int* pn;
long* pl;
long long *pll;
float* pf;
double* pd;
// 赋值为100
pc = 100;
ps = 100;
pn = 100;
pl = 100;
pll = 100;
pf = 100;
pd = 100;
// 均加1
pc = pc + 1;
ps = ps + 1;
pn = pn + 1;
pl = pl + 1;
pll = pll + 1;
pf = pf + 1;
pd = pd + 1;
// 查看值
printf("pc=%u\n", pc);
printf("ps=%u\n", ps);
printf("pn=%u\n", pn);
printf("pl=%u\n", pl);
printf("pll=%u\n", pll);
printf("pf=%u\n", pf);
printf("pd=%u\n", pd);
return 0;
}
编译后,我们发现编译器提示我们,不能将int类型转换为指针类型。
这个错误应该是意料之中的,指针类型可以记录两种信息,一个是首地址,一个是目标数据空间大小。
而整型数据的值可以被当作首地址,但是目标数据空间大小却无法表示。赋值操作符两边提供的信息不统一,那么肯定无法成功赋值。
既然无法直接赋值,我们将整型转换为对应的指针类型后,再进行赋值。
#include <stdio.h>
int main()
{
char* pc;
short* ps;
int* pn;
long* pl;
long long *pll;
float* pf;
double* pd;
// 现将整型转换为对应的指针类型再赋值
pc = (char *)100;
ps = (short *)100;
pn = (int *)100;
pl = (long *)100;
pll = (long long *)100;
pf = (float *)100;
pd = (double *)100;
pc = pc + 1;
ps = ps + 1;
pn = pn + 1;
pl = pl + 1;
pll = pll + 1;
pf = pf + 1;
pd = pd + 1;
printf("pc=%u\n", pc);
printf("ps=%u\n", ps);
printf("pn=%u\n", pn);
printf("pl=%u\n", pl);
printf("pll=%u\n", pll);
printf("pf=%u\n", pf);
printf("pd=%u\n", pd);
return 0;
}
现在编译可以通过了,让我们仔细观察结果。
所有的指针内保存的首地址一开始均为100,加1后,现在变成了不同的值。
与初始值相比,分别移动了:1、2、4、4、8、4、8。
如果稍微数值敏感一点,你应该可以看出这些数值分别是对应的目标数据对象的空间大小。
sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(long) = 4
sizeof(long long) = 8
sizeof(float) = 4
sizeof(double) = 8
指针类型加1后,将首地址向后移动了sizeof(目标数据对象)
字节。
我们再让指针加2试试看?
pc = pc + 2;
ps = ps + 2;
pn = pn + 2;
pl = pl + 2;
pll = pll + 2;
pf = pf + 2;
pd = pd + 2;
与初始值相比,分别移动了:2、4、8、8、16、8、16。
指针类型加2后,将首地址向后移动了两个sizeof(目标数据对象)
字节。
pc = pc - 1;
ps = ps - 1;
pn = pn - 1;
pl = pl - 1;
pll = pll - 1;
pf = pf - 1;
pd = pd - 1;
指针类型与整型也可以进行减法运算。指针类型减1后,将首地址向前移动了sizeof(目标数据对象)
字节。
规律:
sizeof(目标数据对象)
被称作步长。
指针类型加n
后。其首地址向后移动n * 步长
字节。
指针类型减n
后。其首地址向前移动n * 步长
字节。