C言語で構造体のネットワークバイトオーダー変換


以下のような構造体があるのですが、  
ビッグエンディアン、リトルエンディアン関係なく、  
ネットワークバイトオーダーへ変換できる(もしくは型定義できる)コードを書きたいと思っています。  
[構造体]

[code]

    struct sample {
    　　unsigned short a:12;
    　　unsigned short b:2;
    　　unsigned short c:2;
    };
    
[/code]

↓これで問題ないですか？

[code]

    struct sample val = {300,1,2};
    htons((uint16_t)val);
    
[/code]

もしくは、以下のように定義すれば、htons()で変換しなくても大丈夫でしょうか？

[code]

    struct sample {
    #if __BYTE_ORDER == __LITTLE_ENDIAN
    　　unsigned short a1:8;　/* aの前半 */
    　　unsigned short c:2;
    　　unsigned short b:2;
    　　unsigned short a2:4;　/* aの後半 */
    #endif
    #if __BYTE_ORDER == __BIG_ENDIAN
    　　/* ビッグエンディアンならそのまま流してOK？ */
    　　unsigned short a:12;
    　　unsigned short b:2;
    　　unsigned short c:2;
    #endif
    };
    
[/code]

ビットフィールドが8以下で、バイトの区切りをまたがなければ




ネットワーク送受信（やファイル読書などの外部入出力）の対象とするデータ表現に、C言語のビットフィールドを用いるのはお勧めしません。

JPCERTの [EXP11-C. ビットフィールド構造体のレイアウトについて勝手な想定をしない](https://www.jpcert.or.jp/sc-
rules/c-exp11-c.html) を参照ください。

>
> ビットフィールド構造体の内部表現には、処理系依存の様々な性質がある(たとえば内部パディング)。また、ビットフィールド構造体には以下に示す処理系依存の制約がある。
>
>   *
> 記憶域単位におけるビットフィールドのアラインメント。たとえば、ビットフィールドは記憶域単位の上端から割り当ててもよいし、下端から割り当ててもよい。
>   * ビットフィールドが記憶域単位の境界をまたいでもよいか否か。
>

>
> 従って、ビットフィールド構造体のメンバのレイアウトに関してある状態を仮定した、移植性があり安全なコードを書くことは不可能である。

ちなみに`__BYTE_ORDER`マクロで切り替えを行っている例ですが、この構造体定義だと変数`a`／`a1`+`a2`にアクセスする箇所全てで`__BYTE_ORDER`マクロ判別が必要になり、無用なコードの複雑化を招くと思います。

