C 標準には次のように記載されています。
適切にキャストされた構造体オブジェクトへのポインターは、その最初のメンバー (または、そのメンバーがビットフィールドの場合は、それが存在するユニット) を指し、その逆も同様です。
問題の構造体の最初のメンバーが匿名の構造体/共用体である場合、C11でそのような「適切なキャスト」を実行する可能な(そして明確に定義された)方法はありますか? または、含まれている構造体が匿名の場合、「その逆」の後方キャストを実行するには?
匿名構造体と同じメンバーシーケンスを持つ非匿名構造体にキャストすると、互換性がないため、これが明確に定義されなくなり、同じメモリレイアウトを持つことが保証されないと思います。
ただし、C 標準には次のように記載されています。
さらに、別々の翻訳単位で宣言された 2 つの構造体、共用体、または列挙型は、それらのタグとメンバーが次の要件を満たしている場合に互換性があります。両方がそれぞれの翻訳単位内のどこかで完了している場合、次の追加要件が適用されます: メンバー間に 1 対 1 の通信が存在するものとします <...>
このルールを無名構造体に適用することはできますか? 次の設定があるとします。
header.h:
struct container {
struct {
int a;
char b;
};
};
void print(struct container *pcontainer);
9月c:
#include <stdio.h>
#include "header.h"
void print(struct container *pcontainer){
printf("%d\n", ((struct { int a; char b; }*)pcontainer)->a);
}
main.c:
#include "header.h"
int main(void){
struct container container, *pcontainer;
pcontainer = &container;
pcontainer->a = 1;
print(pcontainer);
return 0;
}
(これはgcc (GCC) 4.8.3 20140911でコンパイルされ、1 が出力されます)。
print
関数内のキャストで使用される無名構造体と、 の最初のメンバーである無名構造体を考えてみましょstruct container
うmain.c
。それらは「別々の翻訳単位で宣言された型」と見なすことができますか? また、他のすべての互換性要件を本当に満たしていますか、それとも何か誤解していますか?