指针算术

指针添加

给定一个指针和一个标量类型 N,求值为指向指向类型的 Nth 元素的指针,该元素直接跟随内存中的指向对象。

int arr[] = {1, 2, 3, 4, 5};
printf("*(arr + 3) = %i\n", *(arr + 3)); /* Outputs "4", arr's fourth element. */

指针是用作操作数值还是标量值无关紧要。这意味着像 3 + arr 这样的东西是有效的。如果 arr[k] 是数组的 k+1 成员,则 arr+k 是指向 arr[k] 的指针。换句话说,arrarr+0 是指向 arr[0] 的指针,arr+1 是指向 arr[2] 的指针,依此类推。一般来说,*(arr+k)arr[k] 相同。

与通常的算术不同,将 1 添加到指向 int 的指针会将 4 字节添加到当前地址值。由于数组名称是常量指针,+是我们可以使用数组名称通过指针表示法访问数组成员的唯一运算符。但是,通过定义指向数组的指针,我们可以更灵活地处理数组中的数据。例如,我们可以按如下方式打印数组的成员:

#include<stdio.h>
static const size_t N = 5
    
int main()
{
    size_t k = 0;
    int arr[] = {1, 2, 3, 4, 5};
    for(k = 0; k < N; k++)
    {
        printf("\n\t%d", *(arr + k));
    }
    return 0;
}

通过定义指向数组的指针,上述程序等效于以下内容:

#include<stdio.h>
static const size_t N = 5
    
int main()
{
    size_t k = 0;
    int arr[] = {1, 2, 3, 4, 5};
    int *ptr = arr; /* or int *ptr = &arr[0]; */
    for(k = 0; k < N; k++)
    {
        printf("\n\t%d", ptr[k]);
        /* or   printf("\n\t%d", *(ptr + k)); */
        /* or   printf("\n\t%d", *ptr++); */
    }
    return 0;
}

看到使用运算符+++访问数组 arr 的成员。可以与指针 ptr 一起使用的其他运算符是 ---

指针减法

给定两个指向同一类型的指针,求值为 ptrdiff_t 类型的对象,该对象保存必须添加到第二个指针的标量值,以获得第一个指针的值。

int arr[] = {1, 2, 3, 4, 5};
int *p = &arr[2];
int *q = &arr[3];
ptrdiff_t diff = q - p;

printf("q - p = %ti\n", diff); /* Outputs "1". */
printf("*(p + (q - p)) = %d\n", *(p + diff)); /* Outputs "4". */