

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

[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以下で、バイトの区切りをまたがなければ


CC BY-SA 3.0
2016-05-23T14:03:42.787
25114
2016-05-24T00:38:00.070
2016-05-23T14:17:58.537
3605
15606
question
c
C言語で構造体のネットワークバイトオーダー変換


ビットフィールドに使用が許されているのは`_Bool`、`signed int`、`unsigned
int`であり、それ以外は実装依存となります。またビットフィールドのビットがどのように埋められるかについても実装依存となります。  
ネットワークバイトオーダーを意識されるとのことで、その場合、複数プラットフォーム、複数コンパイラーでのコンパイルを前提とされていると思いますが、であれば実装依存なコードはあまりお勧めしません。

ただし、[Visual C++](https://msdn.microsoft.com/ja-
jp/library/yszfawxh.aspx)や[GCC](https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Structures-
unions-enumerations-and-bit-fields-implementation.html#Structures-unions-
enumerations-and-bit-fields-
implementation)には実装依存の振る舞いが記されています。他のコンパイラーについてもこのような記述を確認し、満足できるのであれば挙げられたコードでも構わないと思います。


CC BY-SA 3.0
2016-05-23T21:30:02.143
25124
2016-05-23T21:30:02.143
4236
25114
answer


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

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

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

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

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


CC BY-SA 3.0
2016-05-24T00:38:00.070
25126
2016-05-24T00:38:00.070
49
25114
answer