为什么这段代码打印地址?

时间:2017-08-25 14:50:34

标签: c multidimensional-array

为什么在意外打印2D数组的一个维度时没有出现编译时错误?

#include <stdio.h>

void main() {
    int i;
    int arr[2][3] = { 1, 2, 3, 4, 5, 6 }; //<- Declared a 2D array

    for (i = 0; i < 6; i++) {
        printf("%d\n", arr[i]);  // <- Accidently forgot a dimension
    }
}

我应该收到编译时错误,但我收到了一组地址!为什么? arr[0]在此上下文中对编译器的意义是什么?

2 个答案:

答案 0 :(得分:8)

数组类型的表达式在大多数上下文中计算为指向第一个数组元素的指针(一个值得注意的例外,其中包括sizeof运算符)。

在您的示例中,arr[i] 具有数组类型。因此它评估为类型为int (*)[]的指针(指向数组的指针)。这就是印刷品。使用%d打印指针是未定义的行为,因为printf()会将指针读取为int

答案 1 :(得分:1)

菲利克斯帕尔曼的答案解释了观察到的行为。

关于你的第二个问题:你没有得到警告的原因是你没有要求它们。

默认情况下,编译器非常宽容,并且会接受包含明显未定义行为的损坏代码。这个特殊的一个并不明显,因为printf()在初始格式字符串之后接受任意数量的额外参数。

您可以指示编译器发出许多有用的警告,以避免愚蠢的错误并检测非明显的编程错误。

  • gcc -Wall -Wextra -Werror
  • clang -Weverything -Werror
  • 选项/W3/W4与Microsoft Visual Studio。

gccclang会抱怨数组arr的草率初始值设定项。它应该是:

int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };

打印循环确实令人惊讶,你真的想用一个循环打印数组吗?

另请注意,没有参数的main的标准原型是int main(void)