趣味プログラマによるOSS開発日誌

趣味で作っているOSSソフトウェアの紹介や関連技術の紹介、楽曲製作、Webデザイン勉強状況を紹介します。

範囲指定による配列の初期化

前回に引き続き他の人が作成したプログラムを読んでいる時に学んだことを共有します。
今回は配列の初期化に関する話題です。
※ただしここで紹介するのは、GNU Cの拡張機能です。

配列の初期化(単純に行う場合)

C言語で配列を宣言したと同時に初期値を代入する時、通常であれば以下のように行うと思います。
この方法では要素に対応する値が正しいことを確認するために、確認が必要になってしまいます。
これは要素数が増えてくると面倒ですし、間違えやすそうですよね。

int arr[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 0 };

配列の初期化(実行時に初期化)

配列の初期化を実行時に初期化するという方法も考えられます。
以下では、あえてswitch文で要素ごとに代入する値を変更するコードを示しました。
if文にすれば少しは綺麗になるよという意見もあると思いますが、より複雑な初期化を行う場合には結局破綻してしまいます。

#define NUM_OF(x) sizeof(x) / sizeof(x[0])

int arr[16];
int i;

for(i = 0; i < NUM_OF(arr); ++i){
  switch(i){
    case 0:
    case 1:
    case 2:
    case 15:
      arr[i] = 0;
      break;
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
      arr[i] = 1;
      break;
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
    case 14:
      arr[i] = 2;
      break;
    default:
      break;
  }
}

配列の初期化(GNU C拡張を利用)

ここでGNUのC拡張を利用すると以下のようなコードで初期化することが出来ます。
非常に分かりやすいですね。

int arr[16] = {
  [0 ... 2]   = 0,
  [3 ... 8]   = 1,
  [9 ... 14]  = 2,
  [15]        = 0,
};

サンプルコード

GNU C拡張を利用して、配列の初期化を行った時のサンプルコードを以下に示します。

#include <stdio.h>
 
#define NUM_OF(x) sizeof(x) / sizeof(x[0])
 
int arr[16] = {
  [0]         = 0,
  [1]         = 0,
  [2]         = 0,
  [3 ... 8]   = 1,
  [9 ... 14]  = 2,
  [15]        = 0,
};
 
int main()
{
  int i;
 
  for(i = 0; i < NUM_OF(arr); ++i){
    printf("arr[%d] = %d\n", i, arr[i]);
  }
 
  return 0;
}

実行結果

サンプルコードを実行した結果を以下に示します。
配列がきちんと初期化されていることを確認することが出来ました。

$ gcc array.c -o array
$ ./array
arr[0] = 0
arr[1] = 0
arr[2] = 0
arr[3] = 1
arr[4] = 1
arr[5] = 1
arr[6] = 1
arr[7] = 1
arr[8] = 1
arr[9] = 2
arr[10] = 2
arr[11] = 2
arr[12] = 2
arr[13] = 2
arr[14] = 2
arr[15] = 0