有人可以解释,为什么
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
我认为这与这些变量的字节大小有关。 但我不明白输出的第二行。
答案 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)。