需要IP头解释

时间:2013-11-27 00:48:25

标签: c network-programming c-preprocessor

我有两个完全相同的代码:

    struct sniff_ip {
        u_char ip_vhl;      /* version << 4 | header length >> 2 */
            ...
    };
#define IP_HL(ip)       (((ip)->ip_vhl) & 0x0f)
    #define IP_V(ip)        (((ip)->ip_vhl) >> 4)

struct sniff_ip {
        uint8_t ip_hl:4;
        uint8_t ip_ver:4;
            ...
    };

前者是来自http://www.tcpdump.org/pcap.html

的代码

后者是我的

这两个代码的IP版本和IP头长度改变位置,但输出是相同的,为什么?

我的意思是#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)查看后四位,当声明uint8_t ip_hl:4捕获前四位时...

1 个答案:

答案 0 :(得分:2)

不要使用位域来实现协议!确切位置取决于ABI并且取决于平台/编译器。

你的假设

  

当uint8_t ip_hl:4被声明为捕获前四位时

是错误的。对您的编译器有效,但不能一般化。您必须非常仔细地阅读编译器/ ABI文档,以找出真正放置位的位置。

如何定义位域的示例可以在ARM EABI规范http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf&#34; 7.1.7位域&#34;中找到。但对于x86或mips ABI来说,这可能完全不同

编辑:

Bitfields可以节省空间(例如unsigned int flag:1bool flag)[这种假设可能不成立,因为检查需要更多(和更慢)的机器代码]并使代码更容易阅读(例如if (a->flags & (1 << 0))if (a->some_flag))。但你永远不能依赖确切的职位。