C言語のフレキシブル配列メンバ(flexible array member)、通称struct hack

C/C++

PHPの内部実装がC言語なのは周知の事実かと思いますが、最近仕事でPHP7の内部実装をみる機会がありました。
そこで学んだC言語のflexible array member、通称struct hackというテクニックがなかなか面白かったので、忘れないようメモです。

ちなみに、このサイトの説明がわかりやすいです。
https://www44.atwiki.jp/bokuyo/pages/118.html

struct hack

struct hackはどんなテクニックかというと、こんな風に構造体の最後を要素数を定義しない配列にしてもコンパイル通りますよ!っていうテクニックです。
別に構造体の中なら最後じゃなくてもコンパイルは通ると思うんですが、たぶん最後以外はうまい使い方はないです。

ちなみに要素数を指定しない配列は構造体内でしか宣言できなくて、それ以外の場所で使おうとするとコンパイルエラーになります。

ちなみにサイズは0バイト、つまり要素数0の配列と認識されるようです。

struct hackの使いどころ

で、コンパイル通るのわかったけど、こんなん何に使うのよ?っていう話なんですが、こんな感じで使います。

この時のメモリの領域はこんな感じに確保されるので、メモリを解放するまで安全にアクセスできます。
しかも、malloc時にはじめてfugaの要素数を決められるので、構造体毎に異なる要素数を指定できます。

余談:PHP7でのstruct hackの使われ方

PHP7ではstruct hackはこんな感じで使われています。
properties_table[]ではなくproperties_table[1]と書いてるのは、おそらくC99より前のバージョンのC言語ではサイズ0の配列の宣言ができなかったらしいので、その辺の名残りでしょう。

さらに余談ですが、PHP5とPHP7ではこのzend_objectの構造が変わっているため、PHP7ではzend_objectを使って構造体を定義するときは、こんな風にzend_objectを最後に持ってくるようにする必要があります。

参考
https://qiita.com/hnw/items/d615e0d4122f247d4c75

C99の仕様
連載:C言語の最新事情を知る(1)。長い歴史を持ちながら、依然として人気の高いC言語。その最新仕様の情報にキャッチアップするための連載スタート。今回は1999年に策定された「C99」を取り上げる。

コメント

%d人のブロガーが「いいね」をつけました。