使用NULL的指针算术

时间:2014-02-28 19:06:44

标签: c pointers

有人可以解释,为什么

int main(void)
{
    char *a = NULL;
    int *b = NULL;
    double *c = NULL;

    printf("\n%d %d %d\n%d %d %d\n\n",
    (int) (a+1), (int)(b+1), (int)(c+1),
    (int) (a+5), (int)(b+7), (int)(c+17));
    return 0;
}

输出

1, 4, 8
5, 28, 136

我认为这与这些变量的字节大小有关。 但我不明白输出的第二行。

5 个答案:

答案 0 :(得分:14)

如果p是指向T类型的指针,并且它包含内存地址X,则p + N是内存地址X + N * sizeof(T)

(int) (a +  1) == 0 +  1 * sizeof(char)   ==  1 * 1 ==   1
(int) (b +  1) == 0 +  1 * sizeof(int)    ==  1 * 4 ==   4
(int) (c +  1) == 0 +  1 * sizeof(double) ==  1 * 8 ==   8

(int) (a +  5) == 0 +  5 * sizeof(char)   ==  5 * 1 ==   5
(int) (b +  7) == 0 +  7 * sizeof(int)    ==  7 * 4 ==  28
(int) (c + 17) == 0 + 17 * sizeof(double) == 17 * 8 == 136

次要注意:正如Barmar在他的回答中指出的那样,对NULL指针的算术在技术上是未定义的行为。因此,符合标准的编译器可以做出与该算法不同的事情;代码可能打印了1,11415或玩扑克的狗的照片。但是,您观察到的行为与您从有效指针开始时所观察到的定义的行为相同,因此您可能不必担心这一点。

答案 1 :(得分:4)

在C中,指针算法取决于底层类型的大小。

当您在某个指针p + n上执行p时,您实际上并未向其添加n。而是添加n * (sizeof(*p))。那是你用n项推进指针。

答案 2 :(得分:3)

a+5 = 0 + sizeof(char)*5 = 5
b+7 = 0 + sizeof(int)*7 = 28
c+7 = 0 + sizeof(double)*17 = 136

答案 3 :(得分:1)

对空指针的算术会导致未定义的行为,因此任何结果都是可能的。

答案 4 :(得分:1)

NULL上的算术运算 - 指针是未定义的行为。

来自C标准:

  

6.3.2.3指针

     

[...]   3   如果将空指针常量转换为a   指针类型,结果指针,称为空指针,保证比较不等   指向任何对象或函数的指针。

     

[...]

     

6.5.6加法运算符

     

[...]   2   另外,两个操作数都应具有算术类型,或者一个操作数应为a   指向对象类型的指针,另一个指针应具有整数类型。

     

[...]

     

Apx J.2未定义的行为

     

[...]

     

将指针加到或减去数组对象和数组对象   整数类型产生的结果不会指向同一个数组,或者只是指向同一个数组   对象(6.5.6)。