8位输入给出奇怪的行为,因为16/32位给出了小Endian/Big Endian

Udi*_*pta 1 c struct pointers network-programming bit-manipulation

我有这样的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;

};
Run Code Online (Sandbox Code Playgroud)

我在同一个模块中为这样的成员提供了价值 -

   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;
            }
Run Code Online (Sandbox Code Playgroud)

其中arg是传递给该模块的命令行参数.

现在以十六进制格式 - >执行后查看结构的内容

  03 04 20 81

   icmpopt_type: seems fine
   icmpopt_len: seems fine
   prefixlen: seems fine
Run Code Online (Sandbox Code Playgroud)

但是对于其构成字节中的其他3个字段,位看起来相反

  lflag:1; aflag:1; reserved:6
Run Code Online (Sandbox Code Playgroud)

它应该是 - 10100000=A0但实际上它们是=>81=10000001

它给我带来了很多问题......

  1. 和小端/大端有什么关系吗?

  2. 如果是,那么8位的htonl和htons等函数的对应部分是什么.

  3. 如果不是,可能是什么问题或者我完全误解了什么?

  4. 什么是最好的方法?要在结构
    本身内修改这些字段的顺序,还是在这里应用一些位运算符和位移位?

在命令行提供的输入 -

    32+1+0+32 
Run Code Online (Sandbox Code Playgroud)

这个最后的32在这里没有任何意义,因为我已经在模块中修复了32个用于测试.虽然我的实际目的也需要考虑这个领域.

任何替代方法请尽快帮助我.

Thanx提前.

编辑:

在此输入图像描述

这是我需要创建的实际结构,并且随着创建,需要为用户做出规定,通过GUI为所有字段指定值.(现在只能通过linux命令行).

我想我现在已经把问题弄得更清楚了,但如果还需要进一步的信息,我会很乐意补充.

Oli*_*rth 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);
Run Code Online (Sandbox Code Playgroud)

当然,在实践中,你应该使用敏感#define而不是魔术数字(6和7).你可能决定将它包装在一堆setter和getter函数中.