【问题标题】:Why the value of this matrix element is unknown?为什么这个矩阵元素的值是未知的?
【发布时间】:2016-01-14 11:27:02
【问题描述】:

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

如果我们写成int a[][3]={{0},{1},{2}};,那么元素a[1][2]的值就是____。

key 表示它的值是未知的。 由于该语句不允许在函数外部编写,因此不应将矩阵简单地视为一个全局变量,它将所有元素初始化为 0。但是,我认为初始化器 {{0},{1},{2}} 等效于 {{0,0,0},{1,0,0},{2,0,0}},所以 @ 987654326@应该是0。谁错了,钥匙还是我?

PS:我写了这段代码:

#include <stdio.h>

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

它的输出正好是0。

【问题讨论】:

  • int a[ ][3] ;与int ( *a )[3] 相同,其中 a 是指向 3 个整数数组的指针。并且由于您已经初始化了zeroth 元素,其余元素将被分配默认值“0”。
  • C 不支持不完整的初始化。要么全部,要么没有。
  • @SKD 不不不。 a 不是指针,它是一个正确的编译时数组。大小由编译器简单地推导出,具体取决于初始化程序。 a 是由三个int 组成的三个 数组。
  • @SKD 是这样,但是int a[][3] 那么a 不是指针,它与指针不同,它不等同于指针。这是一个数组。

标签: c multidimensional-array initialization initializer-list


【解决方案1】:

你是对的,其余的值被初始化为默认值,在这种情况下为 0。

标准中的相关引用:

6.7.9 初始化

  1. 如果大括号括起来的列表中的初始值设定项少于元素或成员的数量 用于初始化已知数组的字符串文字中的聚合或更少字符 大小超过数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储持续时间的对象相同。

【讨论】:

    【解决方案2】:

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

    C11, 6.7.9

    如果大括号括起来的列表中的初始值设定项比那里少 是聚合的元素或成员,或 用于初始化已知大小的数组的字符串文字 是数组中的元素,聚合的其余部分应为 隐式初始化与具有静态存储的对象相同 持续时间。

    【讨论】:

      【解决方案3】:

      问题是 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
      

      【讨论】:

        【解决方案4】:

        两个都是对的。

        如果你不初始化一个局部非静态变量,它将有一个不确定的值。但是您初始化a 变量,这就是“赋值”所做的,它初始化变量。如果你初始化一个数组的值比它声明的值少,那么其余的将被初始化为“零”。

        【讨论】:

        • 密钥如何正确?如问题数组元素(第零)已初始化。
        • @SKD 对于 未初始化 变量,“key”(无论是什么)都是正确的。如果一个人没有显式地初始化一个局部(非静态)变量,那么它将被未初始化。并且 OP 也是 正确的,因为 OP do 初始化了变量。
        • is correct for uninitialized variables 在这个问题中并非如此。但我很欣赏你的一般解决方案。
        猜你喜欢
        • 2012-08-17
        • 1970-01-01
        • 1970-01-01
        • 2011-04-25
        • 1970-01-01
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多