95

次の宣言で

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

すべてゼロの配列を取得しますが、次の配列を使用します

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

すべて1つの値を持つ配列を取得しません。デフォルト値は0のままです。

なぜこの動作をし、どのようにすべて1で初期化できますか?

編集:memset値を1として使用すると、各バイトが1に設定されるため、各配列セルの実際の値は1ではなく。になることを理解しました16843009。1に設定するにはどうすればよいですか?

4

7 に答える 7

137

「すべてのアイテムを1つに設定する」という意味で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

2D配列をゼロで初期化するには、次の方法を使用します。 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までの範囲を指定しますが、Cは..トークンとして使用しないため、使用されなかったのは当然のことです。

表記の前後のスペース...は基本的に必須であることに注意してください。それらが数値に付加されている場合、その数値は浮動小数点数として解釈されます。たとえば、0...9は、、、としてトークン化され、0.浮動小数点数は配列の添え字として許可されません。名前付き定数を使用すると、問題は発生しませんが、安全な習慣を身に付けることをお勧めします。..9...ROW-1


補遺:

ちなみに、GCC7.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 } };

たぶん、標準化委員会はそれを検討するでしょうか?

于 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 に答える