C言語のイディオムに潜む未定義

S・P・ハービソン3世とG・L・スティール・ジュニアのCリファレンスマニュアル*1を読んでいたら可変長の構造体の利用について、未定義であると書かれていて驚いた。ググってみたら初級C言語Q&Aに次のとおり説明が。

Q 【可変長の構造体】

 次のような構造体を見かけた。 handle の部分には、実際は長い文字列を格納できるようである。これは正しい書き方か。

struct nameholder {
    int id;
    char handle[1];
};

(中略)
int a[10];

 と宣言した場合に、仕様で許されるのは、 a[0] 〜 a[9] 、 a 、 a+1 〜 a+9 、 a+10 へのアクセスである、ということです。従って、 char handle[1]とした場合に、 handle[0]から後ろをアクセスするのは仕様に反するという解釈をせざるを得ません。


Windows APIでも一部にこういった構造体を要求するものがあり、ごく一般的な手法なわけだけど、規格としては未定義らしい。ちなみにC99では構造体の最後のメンバを可変配列メンバとすることで、合法的に可変長の構造体を扱うことができる(ただしVC++はC99をサポートしていない)。

*1:タイトルながいよ。