C语言在指针算术中做额外的缩放

示例

在指针算术中,要与指针相加或相减的整数不是解释为地址更改,而是解释为要移动的元素数。

#include <stdio.h>

int main(void) {
    int array[] = {1, 2, 3, 4, 5};
    int *ptr = &array[0];
    int *ptr2 = ptr + sizeof(int) * 2; /* wrong */
    printf("%d %d\n", *ptr, *ptr2);
    return 0;
}

此代码在计算分配给的指针时会进行额外的缩放ptr2。如果sizeof(int)为4(这是现代32位环境中的典型值),则表达式表示“ 8个元素在array[0]”之后,该值超出范围,并调用未定义的行为

要ptr2指出之后的2个元素是什么array[0],只需添加2。

#include <stdio.h>

int main(void) {
    int array[] = {1, 2, 3, 4, 5};
    int *ptr = &array[0];
    int *ptr2 = ptr + 2;
    printf("%d %d\n", *ptr, *ptr2); /* "1 3" will be printed */
    return 0;
}

使用加法运算符的显式指针算法可能会造成混淆,因此使用数组下标可能会更好。

#include <stdio.h>

int main(void) {
    int array[] = {1, 2, 3, 4, 5};
    int *ptr = &array[0];
    int *ptr2 = &ptr[2];
    printf("%d %d\n", *ptr, *ptr2); /* "1 3" will be printed */
    return 0;
}

E1[E2]与(*((E1)+(E2)))(N1570 6.5.2.1,第2段)相同,并且&(E1[E2])等效于((E1)+(E2))(N1570 6.5.3.2,脚注102)。

或者,如果首选指针算术,则将指针强制转换为寻址不同的数据类型可以允许字节寻址。但是要小心:字节序可能会成为一个问题,转换为“字符指针”以外的类型会导致严格的别名问题。

#include <stdio.h>

int main(void) {
    int array[3] = {1,2,3};  // 4字节* 3分配
    unsigned char *ptr = (unsigned char *) array;  // 无符号字符仅占用1字节
    /*
     * Now any pointer arithmetic on ptr will match
     * bytes in memory.  ptr can be treated like it
     * was declared as: unsigned char ptr[12];
     */

    return 0;
}