为什么这个矩阵元素的值是未知的?

Why the value of this matrix element is unknown?

这是我练习本上的一道题:

If we write int a[][3]={{0},{1},{2}};, the value of the element a[1][2] will be ____.

钥匙说它的价值无法得知。 由于不允许在函数外部编写语句,因此不应将矩阵简单地视为将所有元素初始化为 0 的全局变量。但是,我认为初始化器 {{0},{1},{2}} 等同于 {{0,0,0},{1,0,0},{2,0,0}},所以a[1][2]应该是0。谁错了,关键还是我?

PS:我写了这段代码:

#include <stdio.h>

int main()
{
    int a[][3]={{0},{1},{2}};
    printf("%d",a[1][2]);
    return 0;
}

它的输出正好是0。

都对。

如果您不初始化局部 non-static 变量,它将具有不确定的值。但是你 do 初始化 a 变量,这就是 "assignment" 所做的,它初始化变量。如果你用比声明的值少的值初始化一个数组,那么其余的将被初始化为 "zero".

你是对的,其余值都初始化为默认值,在本例中为 0。

相关引用自标准:

6.7.9 Initialization

  1. If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

你的答案是正确的,关键是错误的。您未初始化的其余数组成员将被隐式初始化为 0,这是由 C 标准保证的,无论数组是全局数组还是在函数内部。

C11, 6.7.9

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

问题是 C 对于如何解释大括号有松散的规则,大括号没有指定每个数组中有多少项。所以你最终会得到一个 int [3][3]; 的数组,这可能是也可能不是你所期望的。

根据数组初始化规则,每个数组中未显式初始化的项目将被初始化,就好像它们具有静态存储持续时间一样。即归零。

所以你是对的,你可以通过打印内存的原始内容轻松证明这一点,如下所示:

#include <stdio.h>
#include <inttypes.h>
#include <string.h>

void mem_dump (int a[3][3], size_t size);

int main()
{
  int a[][3]={{0},{1},{2}};
  printf("a is initialized like this:\n");
  mem_dump(a, sizeof(a));
  printf("\n"); 

  int rubbish[3][3];
  memset(rubbish, 0xAA, sizeof(rubbish)); // fill up with some nonsense character
  memcpy(a, rubbish, sizeof(a)); // a guaranteed to contain junk.
  printf("a is now filled with junk:\n");
  mem_dump(a, sizeof(a)); 
  printf("\n");

  memcpy(a, (int[][3]){{0},{1},{2}}, sizeof(a)); // copy back the initialized values
  printf("a now contains the initialized values once more:\n");
  mem_dump(a, sizeof(a));

  return 0;
}

void mem_dump (int a[3][3], size_t size)
{
  for (size_t i=0; i<size; i++)
  {
    printf("%.2" PRIx8 " ", ((uint8_t*)a)[i] );

    if( (i+1) % sizeof(int[3]) == 0) // if divisible by the size of a sub array
      printf("\n");
  }
}

输出:

a is initialized like this:
00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00
02 00 00 00 00 00 00 00 00 00 00 00

a is now filled with junk:
aa aa aa aa aa aa aa aa aa aa aa aa
aa aa aa aa aa aa aa aa aa aa aa aa
aa aa aa aa aa aa aa aa aa aa aa aa

a now contains the initialized values once more:
00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00
02 00 00 00 00 00 00 00 00 00 00 00