con*_*boy 0 c arrays pointers pointer-arithmetic
你能解释一下输出如何-4吗?我认为++pp;是UB,但不确定。您的解释将真正有助于理解。big-endian 或 little-endian 机器的输出可能有什么不同吗?
#include <stdio.h>
int a[] = { -1, -2, -3, -4 };
int b[] = { 0, 1, 2, 3 };
int main(void)
{
int *p[] = { a, b };
int **pp = p;
printf("a=%p, b=%p, p=%p, pp=%p\n", (void*)a, (void*)b, (void*)p, (void*)pp);
++pp;
printf("p=%p, pp=%p *pp=%p\n", (void*)p, (void*)pp, (void*)*pp);
++*pp;
printf("p=%p, pp=%p *pp=%p\n", (void*)p, (void*)pp, (void*)*pp);
++**pp;
printf("%d\n", (++**pp)[a]);
}
Run Code Online (Sandbox Code Playgroud)
我的输出:
a=0x107121040, b=0x107121050, p=0x7ffee8adfad0, pp=0x7ffee8adfad0
p=0x7ffee8adfad0, pp=0x7ffee8adfad8 *pp=0x107121050
p=0x7ffee8adfad0, pp=0x7ffee8adfad8 *pp=0x107121054
-4
Run Code Online (Sandbox Code Playgroud)
当您使用数组的名称时(在大多数情况下),它会衰减为指向其第一个元素的指针。这意味着int* p = a;和int* p = &a[0];完全相同。
因此,要了解在这种情况下会发生什么,只需逐步完成即可。在您第一次printf调用时,事情看起来像这样:
pp p a
+-------+ +------+ +----+----+----+----+
| +---------> +--------> -1 | -2 | -3 | -4 |
+-------+ | | +----+----+----+----+
| |
+------+ b
| | +----+----+----+----+
| +---------> 0 | 1 | 2 | 3 |
| | +----+----+----+----+
+------+
Run Code Online (Sandbox Code Playgroud)
pp指向 的第一个元素p,它是指向 的第一个元素的指针a。
现在,当您增加 时pp,它会更改为指向 的第二个元素p,它是指向 的第一个元素的指针b:
pp p a
+-------+ +------+ +----+----+----+----+
| + | | +--------> -1 | -2 | -3 | -4 |
+---|---+ | | +----+----+----+----+
| | |
| +------+ b
| | | +----+----+----+----+
+---------> +---------> 0 | 1 | 2 | 3 |
| | +----+----+----+----+
+------+
Run Code Online (Sandbox Code Playgroud)
然后你增加*pp. 由于*pp是指向 的第一个元素的b指针,因此该指针递增以指向 的第二个元素b:
pp p a
+-------+ +------+ +----+----+----+----+
| + | | +--------> -1 | -2 | -3 | -4 |
+---|---+ | | +----+----+----+----+
| | |
| +------+ b
| | | +----+----+----+----+
+---------> | | 0 | 1 | 2 | 3 |
| + | +----+-^--+----+----+
+---|--+ |
+---------------+
Run Code Online (Sandbox Code Playgroud)
然后你增加**pp. 此时pp是指向 的第二个元素的指针p,*pp也是指向 的第二个元素的指针b。这意味着**pp命名 的第二个元素b。您将其从1增加到2:
pp p a
+-------+ +------+ +----+----+----+----+
| + | | +--------> -1 | -2 | -3 | -4 |
+---|---+ | | +----+----+----+----+
| | |
| +------+ b
| | | +----+----+----+----+
+---------> | | 0 | 2 | 2 | 3 |
| + | +----+-^--+----+----+
+---|--+ |
+---------------+
Run Code Online (Sandbox Code Playgroud)
现在,让我们剖析一下(++**pp)[a]。 ++**pp与之前相同,因此 的第二个元素b增加到3。
现在,对于任何指针ptr和整数n,ptr[n]都与 相同*(ptr + n)。由于加法是可交换的,ptr + n因此与 相同n + ptr。这意味着ptr[n]与n[ptr].
将这些放在一起,这意味着(++**pp)[a]与 相同3[a],与 相同a[3]。 a[3]是-4,因此您的结果。