在多维数组中,为什么再次取消引用行地址会导致地址而不是值

时间:2018-06-27 14:40:16

标签: c pointers multidimensional-array

#include <stdio.h>

void main() {
    int a[4][3] = {
        { 3, 5, 7 },
        { 2, 4, 67 },
        { 21, 8, 9 },
        { 2, 45, 6 }
    };
    printf("%u ", *(&a[0]+1));
}

表达式(&a[0]+1)给出&a[1],输出应为2,但是上述代码的输出为&a[1],为什么?这似乎很愚蠢,但请帮助我。

2 个答案:

答案 0 :(得分:5)

您注意到&a[0]+1&a[1]a[1]是3 int的数组,因此&a[1]是3 int的数组的地址。

这意味着*&a[1]是3 int的数组。在C语言中,数组会自动转换为其第一个元素的地址(除非它是sizeof,一元&_Alignof的操作数,或者是用于初始化的字符串文字)数组)。因此*&a[1]自动成为&a[1][0]

由于这是一个指针,因此不应使用%u打印。正确的打印方法是:

printf("%p\n", (void *) *(&a[0]+1));

但是,假设您确实使用过%u,似乎发生了什么事,该程序打印了重新解释为unsigned int的指针的值。这不是您应该依靠的行为。

答案 1 :(得分:3)

  

表达式(&a[0]+1)给出&a[1]

是的

  

,输出应为2

否。

  

但是以上代码的输出是&a[1]为什么?

您要问的是

的作用
printf("%u ",*(&a[0]+1));

。我们已经确定(&a[0]+1)等效于&a[1]。因此,*(&a[0]+1)等效于*(&a[1]),而后者依次等效于a[1]。尽管a[1]是第一个数组元素的值,2的值是一个数组,而不是2

您的上下文不是数组值无法衰减到指针的少数情况,因此整个函数调用实际上等效于

printf("%u ", &a[1][0]);

但是,此时我们遇到了障碍。 %u伪指令必须与(提升的)类型unsigned int的实参相对应,而实际实参则具有指针类型。这种不匹配导致不确定的行为。看起来是合理的,但绝不能保证,这表明您在打印对应于部分或全部指针位模式的十进制整数。

如果要打印a[1]的第零个元素,则最简单地将其写为a[1][0],但也可以将其写为*a[1]**&a[1]**(&a[0] + 1)或其他多种形式。