「配列の初期化 指示付きの初期化指定子」の版間の差分
提供: C言語入門
(ページの作成:「C言語の配列は、配列の宣言時に初期化することができます。C99で追加された配列の指示付き初期化指定子により、従来より...」) |
(相違点なし)
|
2014年3月31日 (月) 15:55時点における最新版
C言語の配列は、配列の宣言時に初期化することができます。C99で追加された配列の指示付き初期化指定子により、従来よりもコードのわかりやすさや柔軟な初期化ができるようになりました。
読み方
- 指示付きの初期化指定子
- しじつき の しょきかしていし
目次
概要
従来までのC言語の配列の初期化では、要素を指定できませんでした。配列の要素数が増えるにしたがって、どの要素を初期化しているコードなのか、見通しが悪くなる問題がありました。
// 従来の初期化 int a[3] = { 1, 2, 3 };
C99で導入された、「指示付きの初期化指定子」で初期化する場合、要素を指定して、初期化ができるため、見通しが良くなります。
int a[3] = { [0] = 1, [1] = 2, [2] = 3 };
配列サイズを指定せず、以下の初期化を行う場合、要素数が 10 で、 0番から9番が0で初期化され、10番目(要素9)が9で初期化されます。
int a[] = { [9] = 9 };
指示付きあり、と、指示なしを混在させたケースは、以下の通りです。
int a[] = { [3] = 3, 4, [8] = 8, 9 };
上記のコードは、以下の初期化が行われるのと同義です。
a[0] = 0; a[1] = 0; a[2] = 0; a[3] = 3; a[4] = 4; a[5] = 0; a[6] = 0; a[7] = 0; a[8] = 8; a[9] = 9;
C99の配列の指示付き初期化の罠
初期化は、上から順番に評価されます。 このコードがおかしいのは、3番目の要素(a[2])が2回初期化されている点です。
int a[] = { [2] = 33, [1] = 22, 55 // <- [2] = 55 と同義 };
最後を0ターミネートするような配列の初期化を行う場合に、指示付きで、ターミネットの1つ前の指示を「ターミネートの1つ前の指示」を与えないと間違いがおきます。
char a[] = { 1, 2, 0 };
これは、ポインタ配列の最後にNULLを設定しておく、といったときによくあるコードです。
char *str[] = { str1, str2, NULL };
指示付きは、指示があるため、並び順を適当にしても初期化できてしまいます。ターミネートの指示を出さないときに、間違いが起こる可能性があります。
const int ZERO = 0; const int ONE = 1; char a[] = { [ONE] = 2, [ZERO] = 1, 0 };
意図通りのコードという意味では、以下のコードが正しいです。
char a[] = { [ZERO] = 1, [ONE] = 2, 0 };
もしくは、ターミネートの指示を省略しない、というのが間違いをなくします。ターミネートがあれば、並び順は、自由になります。
const int ZERO = 0; const int ONE = 1; const int TERMINATE = 2; char a[] = { [ZERO] = 1, [ONE] = 2, [TERMINATE] = 0 };
init_array1.c の例
ソースコード init_array1.c
/* * init_array.c * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int a[3] = { [0] = 1, [1] = 2, [2] = 3 }; exit(EXIT_SUCCESS); }
コンパイル
cc init_array1.c -o init_array1
実行例
出力なし。
% ./init_array1
init_array2.c の例
ソースコード init_array2.c
/* * init_array.c * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int a[] = { [9] = 9 }; int i = 0; (void)printf("%ld\n", sizeof(a) / sizeof(int) ); for (i = 0; i < (sizeof(a)/sizeof(int)); i++) { (void) printf("%d ", a[i]); } putchar('\n'); exit(EXIT_SUCCESS); }
コンパイル
cc init_array2.c -o init_array2
実行例
% ./init_array2 10 0 0 0 0 0 0 0 0 0 9
init_array3.c の例
ソースコード init_array3.c
/* * init_array.c * Copyright (C) 2014 kaoru <kaoru@bsd> */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int a[] = { [3] = 3, 4, [8] = 8, 9 }; int i = 0; (void)printf("%ld\n", sizeof(a) / sizeof(int) ); for (i = 0; i < (sizeof(a)/sizeof(int)); i++) { (void) printf("%d ", a[i]); } putchar('\n'); exit(EXIT_SUCCESS); }
コンパイル
cc init_array3.c -o init_array3
実行例
% ./init_array3 10 0 0 0 3 4 0 0 0 8 9
関連項目
- 配列の初期化
- 配列の要素数を調べる
- 配列の初期化 指示付きの初期化指定子