「C言語 ポインタ完全制覇(第2版)」補足000


「6-3-11 要素指示子付きの初期化(C99)」について(2023/06/04)

掲示板での会話より

p.363のList 6-4 desgnated_initializer.cにミスがあるのでは、というご指摘でした。まずは該当のリストをそのまま載せます。

List6-4 designated_initializer.c

  1: #include <stdio.h>
  2: 
  3: typedef struct {
  4:     int a;
  5:     int b;
  6:     int c;
  7:     int array[10];
  8: } Hoge;
  9: 
 10: typedef union {
 11:     int int_value;
 12:     double double_value;
 13: } Piyo;
 14: 
 15: int main(void)
 16: {
 17:     // 構造体についてメンバを指定して初期化。
 18:     // 配列についても、添字を指定して初期化。その後ろに並んだ数値は、
 19:     // 添字で指定した要素の続きに割り当てられる。
 20:     Hoge hoge = {.b = 3, .c = 5, {[3] = 10, 11, 12}};
 21: 
 22:     fprintf(stderr, "hoge.b..%d, hoge.c..%d\n", hoge.b, hoge.c);
 23:     fprintf(stderr, "hoge.array[3..] %d, %d, %d\n",
 24:             hoge.array[3], hoge.array[4], hoge.array[5]);
 25: 
 26:     // 共用体について、メンバを指定して初期化
 27:     Piyo piyo = {.double_value = 123.456};
 28:     fprintf(stderr, "piyo.double_value..%f\n", piyo.double_value);
 29: 
 30:     return 0;
 31: }

ここで説明しているのは「要素指示子付きの初期化」であって、上のリストの30行目では、実際構造体Hogeのメンバbcについてはメンバ名を指定して初期化しています。しかし、その続きのarrayについてはメンバ名を指定していないではないか、とのご指摘でした。

これについては、規格書(JIS X3010:2003)の「6.7.8 初期化」に記載があります。

指示がない場合,現オブジェクト中の部分オブジェクトを,現オブジェクトの型に従う順序で初期化する。すなわち,配列要素は添字の昇順で初期化し,構造体メンバは宣言の順で初期化し,共用体では最初の名前付きメンバを初期化する(127)。

一方,指示が存在する場合,それに続く初期化子を使って要素指示子が示す部分オブジェクトを初期化する。そして要素指示子で示される部分オブジェクトの次の部分オブジェクトから順に初期化を続ける(128)。

ひとつめの段落(指示がない場合~)は、C99以前からある昔ながらの初期化に関する記載です。

ふたつめの段落、「一方,指示が存在する場合~」以降が「要素指示子付きの初期化」の話で、「そして要素指示子で示される部分オブジェクトの次の部分オブジェクトから順に初期化を続ける」とあります。List6-4のarrayは、cの次のメンバですので、この書き方で「順に」初期化されます。

リスト6-4のコメントには、配列について「その後ろに並んだ数値は、添字で指定した要素の続きに割り当てられる。」と書いていますが、構造体メンバについても同様いうことです。同じようにコメントを入れておくべきでしたね。

執筆当時、要素名を指定しなければ次のメンバから順に初期化される、ということを示したくてあえて「.array =」を書かなかったのかどうかはもはや思い出せませんが……

ご指摘、ありがとうございました。


「補足(いいわけ?)」の目次に戻る | 「C言語 ポインタ完全制覇(第2版)」のページに戻る | 著者のWebページトップはこちら

ご意見、ご質問、不具合連絡等は掲示板にお願いいたします。