c-使用一个值初始化整个2D数组

带有以下声明

int array[ROW][COLUMN]={0};

我得到全零但下面的一个数组

int array[ROW][COLUMN]={1};

我没有获得全部值的数组。 默认值为0。

为什么会出现这种现象,以及如何用全1初始化?

编辑:我刚刚了解到,使用memset的值为1,会将每个字节设置为1,因此每个数组单元的实际值不会为1,而是16843009。如何将其设置为1?

Kraken asked 2019-10-07T18:59:38Z
4个解决方案
84 votes

您得到此行为,因为int array [ROW][COLUMN] = {1};并不意味着“将所有项目设置为一个”。 让我尝试逐步解释它是如何工作的。

初始化数组的显式,过于清晰的方法是这样的:

#define ROW 2
#define COLUMN 2

int array [ROW][COLUMN] =
{
  {0, 0},
  {0, 0}
};

但是,C允许您省略数组(或struct / union)中的某些项。 您可以例如编写:

int array [ROW][COLUMN] =
{
  {1, 2}
};

这意味着将第一个元素初始化为1和2,然后将其余元素初始化为“好像它们具有静态存储持续时间”。 C语言中有一条规则,规定所有未由程序员明确初始化的静态存储持续时间对象都必须设置为零。

因此,在上面的示例中,第一行设置为1,2,第二行设置为0,0,因为我们没有为它们提供任何显式值。

接下来,在C中有一条规则允许大括号样式。 第一个例子也可以写成

int array [ROW][COLUMN] = {0, 0, 0, 0};

尽管这当然是不好的样式,但很难阅读和理解。 但这条规则很方便,因为它允许我们编写

int array [ROW][COLUMN] = {0};

这意味着:“将第一行的第一列初始化为0,并将所有其他项目初始化为静态存储持续时间,即将它们设置为零。”

因此,如果您尝试

int array [ROW][COLUMN] = {1};

这意味着“将第一行中的第一列初始化为1,并将所有其他项设置为零”。

Lundin answered 2019-10-07T19:00:49Z
23 votes

如果要将数组初始化为0,则可以使用以下命令,

memset(array, -1, sizeof(array[0][0]) * row * count)

但这仅适用于0-1

user2021512 answered 2019-10-07T19:01:21Z
11 votes
int array[ROW][COLUMN]={1};

这只会将第一个元素初始化为1。其他所有元素都为0。

在第一个实例中,您将执行相同的操作-将第一个元素初始化为0,其余元素默认为0。

原因很简单:对于数组,编译器将使用0初始化您未指定的每个值。

使用for数组,可以使用memset设置每个字节,但这通常不适用于int数组(尽管可以使用0)。

一般的for循环将很快完成此操作:

for (int i = 0; i < ROW; i++)
  for (int j = 0; j < COLUMN; j++)
    array[i][j] = 1;

或可能更快(取决于编译器)

for (int i = 0; i < ROW*COLUMN; i++)
  *((int*)a + i) = 1;
teppic answered 2019-10-07T19:02:19Z
4 votes

请注意,GCC对指定的初始化方法表示法进行了扩展,这对于上下文非常有用。 [0]...[9]也允许使用它,而无需评论(部分原因是它试图与GCC兼容)。

扩展符号允许您使用[0]...[9]来指定要用以下值初始化的元素范围。 例如:

#include <stdio.h>

enum { ROW = 5, COLUMN = 10 };

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = 1 } };

int main(void)
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
            printf("%2d", array[i][j]);
        putchar('\n');
    }
    return 0;
}

毫不奇怪,输出是:

 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1

请注意,Fortran 66(Fortran IV)对数组的初始化程序具有重复计数。 当将指定的初始值设定项添加到语言时,C没有得到它们,这总是让我感到奇怪。 Pascal使用[0]...[9]表示法来指定范围从0到9(含0),但是C没有使用error: braces around scalar initializer [-Werror]作为标记,因此不使用它并不奇怪。

请注意,[0]...[9]表示法周围的空格本质上是必填项。 如果它们附加在数字上,则该数字将被解释为浮点数。 例如,将error: braces around scalar initializer [-Werror]标记为int a = { 1 };..9,并且不允许将浮点数用作数组下标。使用命名的常量...ROW-1不会造成麻烦,但是最好养成安全的习惯。


附加物:

我注意到,GCC 7.3.0拒绝了:

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = { 1 } } };

在标量初始化程序[0]...[9]error: braces around scalar initializer [-Werror])周围还有一组括号。 我不确定这是正确的,因为您通常可以在int a = { 1 };中指定标量周围的括号,这是标准明确允许的。 我也不确定这是不正确的。

我还想知道更好的表示法是否是[0]...[9]-这是明确的,不能与任何其他有效语法混淆,并且避免与浮点数混淆。

int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } };

也许标准委员会会考虑这一点?

Jonathan Leffler answered 2019-10-07T19:03:47Z
translate from https://stackoverflow.com:/questions/15520880/initializing-entire-2d-array-with-one-value