0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C/C++ 配列を特定の値で初期化する方法3選

Posted at

for 文

最もオーソドックスな方法でしょう。
H * W の二次元配列を、標準入力から得た値 x で埋めます。

コード例

C
#include <stdio.h>

#define H 100
#define W 100

int main() {
  int x;
  scanf("%d", &x);

  int A[H][W];
  for (int i=0; i < H; ++i)
    for (int j=0; j < W; ++j)
      A[i][j] = x;

  return 0;
}

memset

H * W の二次元配列を -1 で埋めます。

コード例

C
#include <stdio.h>
#include <string.h>

#define H 100
#define W 100

int main() {
  int A[H][W];
  memset(A, -1, sizeof(A));

  return 0;
}

解説

引数の意味は以下の通りです。

  1. 配列の先頭を指すポインタ
  2. 値(1byte
  3. 配列の大きさ(byte数

char txt[100]; memset(txt, 'A', sizeof(txt)); のように、文字列に対して使う例だと結果をイメージしやすいでしょうか。

memset の欠点

12 など、ほとんどの数は memset で埋めるのに適していません。
memset(A, 1, sizeof(A)) というコード自体には問題ありませんが、配列 A の中身は 1 ではなく 16843009 になってしまいます1

その理由は、引数の解説で byte を強調したところからお察しかもですが、各値が 1byte 単位で埋められていくからです。
int は 32bit == 4byte なので、1byte 単位で 1 (== 0x01) を埋めていくと int の値としては 16843009 (== 0x01010101) になる、という動作だったのでした。

memset が有効な場合

代表例は 0-1 の 2 つです2
0 で初期化するのであれば int A[H][W] = {};3 のように、宣言と同時に初期化する方法も簡単です。
珍しい例では、memset(A, 0x3f, sizeof(A)) として「大きな値」で埋める使い方を競技プログラミングで見かけました。
0x3f が選ばれた理由は、「 2 倍しても型の最大値を超えない、できるだけ大きい数」という競技プログラミング側の要求を満たすからでしょう。

fill_n (C++限定)

H * W の二次元配列を、標準入力から得た値 x で埋めます。

コード例

C++
#include <iostream>
#include <algorithm>
using namespace std;

constexpr int H=100, W=100;

int main() {
  int x;
  cin >> x;

  int A[H][W];
  fill_n(&A[0][0], H*W, x);
}

解説

引数の意味は以下の通りです。

  1. 配列の先頭を指すポインタ
  2. 配列の大きさ(要素の個数)

memset の第二引数と第三引数の役割が逆になったようなインターフェースですね。

memset のコード例からも分かる通り、単に A と書いても配列の先頭を指すポインタが得られます。
しかし、 fill_n は賢く、ポインタ A が持つ配列の大きさの情報を関数内部でも保持しているため、「*A の型と x の型が違う」と怒られてしまいます。
そのため、 &A[0][0] のようにして int * 型のポインタを渡しています。
&A[0][0] の他、(int *)A のようにキャストしてもよいでしょう。

memset ではできなかった 12 での埋めも fill_n ならできます。すばらしいですね。
そもそも C++ なら vector クラスを使えばよいという話はありますが、「動的メモリ確保は避けたい!」といったニーズで、あえて C の配列を使う場合には fill_n の使いどころかもしれません。


以上、配列を特定の値で初期化する方法3選でした。何かの役に立ったら幸いです。

  1. 環境依存ですが、多くの環境でこうなるでしょう。

  2. 環境依存ですが、ほとんどの環境(符号付き整数が2の補数表現である)で「有効な場合」に当てはまるでしょう。

  3. C では、 = {} は NG らしいのですが、問題なく動く環境が多いです(たぶん)。= {0} とすれば OK です。

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?