共用体定義または共用体 typedef に適用される transparent_union 属性は、共用体を
透過共用体 として使用できることを指示します。
透過共用体が関数仮パラメーターの型であり、その関数が呼び出されるときは常に、
その透過共用体は、明示的キャストのないそのいずれかのメンバーの型に一致する、
任意の型の引き数を受け入れることができます。
この関数仮パラメーターに対する引き数は、その共用体型の最初のメンバーの呼び出し規則
を使用して、透過共用体に渡されます。
このため、共用体のすべてのメンバーは、同じマシン表現を持たなければなりません。
透過共用体は、互換性の問題を解決するために複数のインターフェースを使用するライブラリー関数で有用です。
この言語フィーチャーは、C89、C99、および Standard C++ に対する直交拡張であり、GNU C
で開発されたプログラムの移植を容易にするためにインプリメントされています。
この型属性は、共用体または typedef 定義の右中括弧の後に指定しなければ なりません。
union u_t { int a; short b; char c; } __attribute__((__transparent_union__)) U; typedef union { int *iptr; union u2_t *u2ptr; } status_ptr_t __attribute__((__transparent_union__));
型属性 transparent_union は、タグ名を持つ無名共用体に適用することができます。
型属性 transparent_union が、ネストされた共用体の外部共用体に適用される場合、 内部共用体 (その最大メンバー) のサイズを使用して、 外部共用体の他のメンバーと同じマシン表現を持つかどうかを判別します。 例えば、次のような場合です。
union u_t { union u2_t { char a; short b; char c; char d; }; int a; } __attribute__((__transparent_union__));
属性 transparent_union は無視されます。 これは、そのものも共用体である、共用体 u_t の先頭メンバーが 2 バイトの マシン表現を持っているのに対し、共用体 u_t の他のメンバーの型は int であり、そのマシン表現が 4 バイトであるためです。
同じ規則が、構造体である共用体のメンバーにも適用されます。 型属性 transparent_union が適用された共用体のメンバーが struct である場合、メンバーではなく、その struct 全体のマシン表現が評価されます。
制約事項
共用体は、完全な共用体型でなければなりません。
共用体のすべてのメンバーは、共用体の先頭メンバーと同じマシン表現を持たなければなりません。 つまり、すべてのメンバーが、共用体の先頭メンバーと同じ量のメモリーで表現可能でなければ ならない、ということです。 先頭メンバーのマシン表現は、残りの共用体メンバーの最大メモリー・サイズを表します。 例えば、型属性 transparent_union が適用された共用体の先頭メンバーの型が int である場合、その後のすべてのメンバーは、多くても 4 バイトで表現可能でなければなりません。 この透過共用体の場合、1 バイト、2 バイト、または 4 バイトで表現可能なメンバーは有効と見なされます。
共用体の先頭メンバーが浮動小数点型 (float、double、float _Complex、または double _Complex) または Vector 型であることはできません。 ただし、float _Complex 型、double _Complex 型、および Vector 型は、それらが先頭メンバーでないかぎり、透過共用体のメンバーであることができます。 透過共用体のすべてのメンバーが先頭メンバーと同じマシン表現を持たなければならないという制約事項も適用されます。
例
この例は、属性 transparent_union を関数仮パラメーター宣言にどのように適用 できるかを示しています。
void foo( union u_t { int a; short b; char c;} __attribute__((transparent_union)) uu) { printf("uu.b is %d¥n",uu.b); } int main() { short s = 99; foo(s); return 0; }
この例は、Complex 型がどのように透過共用体のメンバーであることができるかを示しています。
union u_t { int i[2]; // This member must has a machine representation of 8 bytes. float _Complex cf; } __attribute__((__transparent_union__)) U; void foo(union u_t uu) { printf("uu.cf is %f¥n",uu.cf); } int main() { float _Complex my_cf = 5.0f + 1.0f * __I; foo(my_cf); return 0; }