1

私はこのようなC構造体を持っています...

struct icmp_prefixopt {
    u_int8_t        icmpopt_type;
    u_int8_t        icmpopt_len;
    u_int8_t        prefixlen;
    u_int8_t        lflag:1;
    u_int8_t        aflag:1;
    u_int8_t        reserved:6;

};

そして私は同じモジュールでこのようなメンバーに値を提供しました-

   popt= (struct icmp_prefixopt *)
                    malloc(sizeof(struct icmp_prefixopt));

  popt->icmpopt_type = 3;
  popt->icmpopt_len = 4;
  popt->prefixlen = (u_int8_t)strtoul(arg, (char **)NULL, 0);

     arg = index(arg, '+');
            if (arg) {
                    ++arg;
                    popt->lflag = ((u_int8_t)strtoul(arg, (char **)NULL, 0))&1;
            }


     arg = index(arg, '+');
            if (arg) {
                    ++arg;
                    popt->aflag = ((u_int8_t)strtoul(arg, (char **)NULL, 0))&1;
            }


     arg = index(arg, '+');
            if (arg) {
                    ++arg;
                 popt->reserved = 32;  //((u_int8_t)strtoul(arg, (char **)NULL, 0))<<2;
            }

ここで、argは、このモジュールに渡されるコマンドライン引数です。

16進形式で実行した後の構造の内容を見てみましょう->

  03 04 20 81

   icmpopt_type: seems fine
   icmpopt_len: seems fine
   prefixlen: seems fine

しかし、ビットは、それらの構成バイトの他の3つのフィールドでは逆になっているように見えます-

  lflag:1; aflag:1; reserved:6

だからそうあるべきだった-10100000=A0しかし実際には彼らは=>81=10000001

それは私に多くの質問を引き起こします...

  1. リトルエンディアン/ビッグエンディアンと関係がありますか?

  2. はいの場合、8ビットのhtonlやhtonsなどの関数に対応するものは何ですか。

  3. いいえの場合、考えられる問題は何でしょうか、または何かを完全に誤解したことがありますか?

  4. 最善のアプローチは何ですか?
    構造自体の中でこれらのフィールドの順序を変更したり、ビットごとの演算子を適用してここでビットをシフトしたりするには?

コマンドラインで提供される入力-

    32+1+0+32 

テスト用にモジュール自体に32を修正したので、この最後の32はここでは目的を果たしません。私の実際の目的はこの分野も考慮する必要がありますが。

別のアプローチですぐに私を助けてください。

よろしくお願いします。

編集:

ここに画像の説明を入力してください

これは私が作成する必要のある実際の構造であり、作成とともに、ユーザーがGUIを介してすべてのフィールドの値を指定できるようにする必要があります。(現在、Linuxコマンドラインからのみ)。

私は今問題をより明確にしたと思いますが、それでもさらに情報が必要な場合は、追加させていただきます。

4

1 に答える 1

5

コンパイラがビットフィールドのパックを選択する方法は、完全に実装に依存します。必ずしもエンディアンとは関係ありません。

htnol(および同様の)ビットフィールドには適用されません。保証付きの注文が必要な場合は、手動で梱包する必要がありuint8_tます。例えば:

struct icmp_prefixopt {
    u_int8_t        icmpopt_type;
    u_int8_t        icmpopt_len;
    u_int8_t        prefixlen;
    u_int8_t        stuff;
}

...

popt->stuff = (lflag << 7) | (aflag << 6);

もちろん、実際に#defineは、魔法数(6と7)ではなく賢明な数を使用する必要があります。そして、これを一連のセッター関数とゲッター関数でラップすることもできます。

于 2013-01-15T22:39:37.020 に答える