.h
C インターフェイスを設計する場合、ユーザー プログラムが知る必要があるものだけをパブリック インターフェイス ( ) に入れるのが一般的です。
したがって、たとえば、構造体の内部コンポーネントは、ユーザー プログラムが知る必要がない場合、非表示のままにしておく必要があります。インターフェイスに影響を与えることなく、構造体の内容と動作が将来変更される可能性があるため、これは確かに良い方法です。
その目的を達成する優れた方法は、不完全型を使用することです。
typedef struct foo opaqueType;
へのポインターのみを使用するインターフェイスをopaqueType
構築できるようになりました。ユーザー プログラムは の内部動作を知る必要はありませんstruct foo
。
ただし、パフォーマンスとメモリの断片化の問題のために、通常はスタック上でそのような構造を静的に割り当てる必要がある場合があります。明らかに、上記の構成でopaqueType
は不完全であるため、そのサイズは不明であるため、静的に割り当てることはできません。
回避策は、次のような「シェル タイプ」を割り当てることです。
typedef struct { int faketable[8]; } opaqueType;
上記の構成では、サイズと配置が強制されますが、構造に実際に何が含まれているかについては詳しく説明しません。したがって、タイプを「不透明」に保つという目的に一致します。
それは主に動作します。しかし、ある状況 (GCC 4.4) では、コンパイラは厳密なエイリアスを壊すと文句を言い、バグのあるバイナリを生成します。
今、私は厳密なエイリアシングについてたくさんのことを読んだので、それが何を意味するのか理解できたと思います.
問題は、厳密なエイリアシング規則を破ることなく、スタックに割り当てることができる不透明な型を定義する方法はありますか?
この優れた記事で説明されているユニオン メソッドを試してみましたが、それでも同じ警告が生成されることに注意してください。
また、visual、clang、および gcc 4.6 以降では、この構成で問題なく動作することに注意してください。
[編集]情報の補足:
テストによると、問題は次の状況でのみ発生します。
- プライベートとパブリックのタイプが異なります。ファイル内で public タイプを private にキャストしてい
.c
ます。彼らが同じ組合の一員であるかどうかは明らかに問題ではありません。public 型に が含まれているかどうかは問題ではありませんchar
。 - private 型のすべての操作が読み取りだけであれば問題ありません。書き込みのみが問題を引き起こします。
- また、自動的にインライン化される関数だけが問題になると思います。
- -O3 設定の gcc 4.4 でのみ問題が発生します。-O2 は問題ありません。
最後に、私のターゲットはC90です。本当に仕方がないのならC99かもしれません。