95

带有以下声明

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

我得到全零的数组,但有以下一个

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

我没有得到所有一个值的数组。默认值仍然是 0。

为什么会出现这种行为以及如何使用全 1 进行初始化?

编辑:我刚刚明白使用memsetwith value as 1,会将每个字节设置为 1,因此每个数组单元格的实际值不会是 1,而是16843009. 如何将其设置为 1?

4

7 回答 7

137

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

初始化数组的明确的、过于清晰的方法是这样的:

#define ROW 2
#define COLUMN 2

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

但是,C 允许您省略数组(或结构/联合)中的一些项目。例如,您可以编写:

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,并将所有其他项设置为零”。

于 2013-03-20T10:47:41.917 回答
48

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

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

但这会起作用0,而且-1只有

于 2013-09-03T13:23:21.997 回答
12
int array[ROW][COLUMN]={1};

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

在第一种情况下,您正在做同样的事情 - 将第一个元素初始化为 0,其余的默认为 0。

原因很简单:对于一个数组,编译器会初始化你没有用 0 指定的每个值。

使用char数组可以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;
于 2013-03-20T10:25:12.273 回答
11

要使用零初始化二维数组,请使用以下方法: int arr[n][m] = {};

注意:上述方法仅适用于初始化为 0;

于 2019-10-13T20:29:52.403 回答
10

请注意,GCC 对指定的初始化符号有一个扩展,这对上下文非常有用。它也被允许clang不加注释(部分是因为它试图与 GCC 兼容)。

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

#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 到 9,但是 C 不用..作标记,所以没有使用也就不足为奇了。

请注意,...符号周围的空格本质上是强制性的;如果它们附加到数字,则该数字被解释为浮点数。例如,0...9将被标记为0., ., .9,并且浮点数不允许作为数组下标。使用命名常量,...ROW-1不会造成麻烦,但最好养成安全的习惯。


附加物:

我顺便注意到 GCC 7.3.0 拒绝:

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

1标量初始化器( )周围有一组额外的大括号error: braces around scalar initializer [-Werror]。我不确定这是正确的,因为您通常可以在标量 in 周围指定大括号int a = { 1 };,这是标准明确允许的。我也不确定这是否不正确。

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

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

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

于 2018-03-04T20:13:01.837 回答
4

改用向量数组:

vector<vector<int>> array(ROW, vector<int>(COLUMN, 1));
于 2019-08-29T06:10:16.750 回答
1
char grid[row][col];
memset(grid, ' ', sizeof(grid));

这是为了将 char 数组元素初始化为空格字符。

于 2020-11-11T14:34:28.823 回答