附有以下声明
int array[ROW][COLUMN]={0};
我得到的数组全是零,但有以下一个
int array[ROW][COLUMN]={1};
我没有得到全为一个值的数组。默认值仍然是 0。
为什么会出现这种行为以及如何使用全 1 进行初始化?
编辑:我刚刚了解到,使用值为 1 的
memset
会将每个字节设置为 1,因此每个数组单元格的实际值不会是 1,而是 16843009
。如何将其设置为 1?
您会得到此行为,因为
int array [ROW][COLUMN] = {1};
的意思是“将所有项目设置为 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,并将所有其他项设置为零”。
至于如何将整个数组初始化为特定值,请参见https://stackoverflow.com/a/13488596/584518
。
-1
memset(array, -1, sizeof(array[0][0]) * row * count)
但这仅适用于
0
和
-1
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;
要将二维数组初始化为零,请使用以下方法:
int arr[n][m] = {};
注意:上面的方法只能用0来初始化;
请注意,GCC 对“指定初始化器”符号进行了扩展,这对于上下文非常有用。
clang
扩展符号允许您使用 ...
来指定要使用以下值初始化的元素范围。例如:
#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(含)的范围,但 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]
)。我不确定这是否正确,因为您通常可以在 int a = { 1 };
中的标量周围指定大括号,这是标准明确允许的。我也不确定这是否正确。
我还想知道是否有更好的表示法是
[0]...[9]
— 这是明确的,不能与任何其他有效语法混淆,并且避免与浮点数混淆。
int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } };
也许标准委员会会考虑这一点?
使用向量
数组代替:
char grid[row][col];
memset(grid, ' ', sizeof(grid));
用于将 char 数组元素初始化为空格字符。
我很好奇除了 c++ 中的数组的 memset 之外还有其他方法吗?