c - 双指针输出说明

标签 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]);
}

我的输出:

a=0x107121040, b=0x107121050, p=0x7ffee8adfad0, pp=0x7ffee8adfad0
p=0x7ffee8adfad0, pp=0x7ffee8adfad8 *pp=0x107121050
p=0x7ffee8adfad0, pp=0x7ffee8adfad8 *pp=0x107121054
-4

Ideone output

最佳答案

当您使用数组名称时(在大多数情况下),它会衰减为指向其第一个元素的指针。这意味着 int* p = a;int* p = &a[0];完全一样。

因此,要了解在这种情况下会发生什么,只需逐步完成即可。在你的第一点 printf打电话,事情看起来像这样:

 pp            p           a
+-------+     +------+     +----+----+----+----+
|   +--------->   +--------> -1 | -2 | -3 | -4 |
+-------+     |      |     +----+----+----+----+
              |      |
              +------+     b
              |      |     +----+----+----+----+
              |  +---------> 0  | 1  | 2  | 3  |
              |      |     +----+----+----+----+
              +------+

pp指向 p 的第一个元素, 这是指向 a 的第一个元素的指针.

现在,当您递增 pp , 它变为指向 p 的第二个元素, 这是指向 b 的第一个元素的指针:

 pp            p           a
+-------+     +------+     +----+----+----+----+
|   +   |     |   +--------> -1 | -2 | -3 | -4 |
+---|---+     |      |     +----+----+----+----+
    |         |      |
    |         +------+     b
    |         |      |     +----+----+----+----+
    +--------->  +---------> 0  | 1  | 2  | 3  |
              |      |     +----+----+----+----+
              +------+

然后您递增 *pp .自 *pp是指向 b 的第一个元素的指针,该指针递增以指向 b 的第二个元素:

 pp            p           a
+-------+     +------+     +----+----+----+----+
|   +   |     |   +--------> -1 | -2 | -3 | -4 |
+---|---+     |      |     +----+----+----+----+
    |         |      |
    |         +------+     b
    |         |      |     +----+----+----+----+
    +--------->      |     | 0  | 1  | 2  | 3  |
              |   +  |     +----+-^--+----+----+
              +---|--+            |
                  +---------------+

然后你递增**pp .此时pp是指向 p 的第二个元素的指针, 所以 *pp是指向 b 的第二个元素的指针.这意味着 **pp命名 b 的第二个元素.您从 1 增加它至 2 :

 pp            p           a
+-------+     +------+     +----+----+----+----+
|   +   |     |   +--------> -1 | -2 | -3 | -4 |
+---|---+     |      |     +----+----+----+----+
    |         |      |
    |         +------+     b
    |         |      |     +----+----+----+----+
    +--------->      |     | 0  | 2  | 2  | 3  |
              |   +  |     +----+-^--+----+----+
              +---|--+            |
                  +---------------+

现在,让我们剖析 (++**pp)[a] . ++**pp和之前一样,所以b的第二个元素增加到 3 .

现在,对于任何指针 ptr和整数 n , ptr[n]*(ptr + n)相同.由于加法是可交换的,ptr + nn + ptr相同.这意味着 ptr[n]n[ptr]相同.

将这些放在一起,这意味着 (++**pp)[a]3[a]相同,与 a[3] 相同. a[3]-4 ,因此你的结果。

关于c - 双指针输出说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56711010/

相关文章:

c - 通过 TCP 发送一个 int 数组时,为什么只有第一个数量是正确的?

c - Vala中如何指定在回调参数之前提供用户数据?

java - 我如何获得数组来保存所玩游戏的数量并为每个玩家运行它?

php - 访问数组中的显式对象

c++ - 为什么 C++11 包含一个关于比较 void 指针的奇怪子句?

在此代码中转换像素

c - "char[] name"和 "char name[]"作为函数参数在 c 中的区别

c - C 数组元素的意外结果

比较C中的unsigned char数组

c - 指针条件 while(*s1++=*s2++)