8-2. 指针运算

  • 学习人数 30K+
  • 适合所有人群学习
avatar
林耿亮

你好编程主讲老师

1.指针运算

上一节中,我们认识了指针类型。指针类型用于保存目标数据对象在内存中的位置。

一个数据对象的内存位置有两个重要信息:

  1. 数据对象的首地址
  2. 数据对象占用存储空间大小

指针类型通过下面的方式,存储这两个重要信息。

  1. 指针类型通过值来保存目标数据对象的首地址
  2. 类型本身标记目标数据对象的空间大小

指针类型的值存储的是内存地址。内存地址是从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;
}

指针加1

现在编译可以通过了,让我们仔细观察结果。
所有的指针内保存的首地址一开始均为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

与初始值相比,分别移动了: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

指针类型与整型也可以进行减法运算。指针类型减1后,将首地址向前移动了sizeof(目标数据对象)字节。

规律sizeof(目标数据对象)被称作步长。
指针类型加n后。其首地址向后移动n * 步长字节。
指针类型减n后。其首地址向前移动n * 步长字节。