结构偏移与位字段

时间:2018-03-08 07:22:22

标签: c data-structures bit-fields

我有一个关于将索引偏移量放到结构中的字段的问题,下面是我用来测试的代码:

#include <stdio.h>
typedef struct ipv4_pkt_struct 
{
    /*ethernet hdr*/
    unsigned char   DestMacAddr[6]      ;
    unsigned char   SrcMacAddr[6]       ;
    unsigned char   EthernetType[2]     ;
    /*IP hdr*/
    unsigned char   Version           :4;
    unsigned char   IHL               :4;
    unsigned char   TypeofService[2]    ;
    unsigned char   Total_Length[4]    ;

} ipv4_pkt_struct_t; 

int main()
{

    ipv4_pkt_struct_t A;

    printf ("%d\n",(unsigned char*)A.TypeofService - (unsigned char*)A.DestMacAddr) ;
    printf("Hello World");

    return 0;
}

输出结果为:

15                                                                                                        
Hello World 

这是正确的,但是如果我做了类似的事情:

printf ("%d\n",(unsigned char*)A.IHL - (unsigned char*)A.DestMacAddr) ;

它会给我一个非常有线的输出:

1296908304                                                                                              
Hello World

printf ("%d\n",(unsigned char*)&A.IHL - (unsigned char*)A.DestMacAddr) ;

给出编译错误:

main.c: In function 'main':
main.c:29:5: error: cannot take address of bit-field 'IHL'
     printf ("%d\n",(unsigned char*)&A.IHL - (unsigned char*)A.DestMacAddr) ;

如何获得正确的偏移?

2 个答案:

答案 0 :(得分:3)

在C位字段中,成员不可寻址。

n1570-§6.5.3.2(p1):

  

一元&运算符的操作数应该是函数指示符,[]或一元*运算符的结果,或者是指定对象的左值的左值不是位字段 [...]

除此之外

printf ("%d\n",(unsigned char*)A.TypeofService - (unsigned char*)A.DestMacAddr) ;  

应该是

printf ("%td\n", A.TypeofService - A.DestMacAddr) ;

答案 1 :(得分:1)

您正在向指针投射(未初始化的)unsigned char;除了访问未初始化的数据是未定义的行为,即使你初始化它,你用值来计算,而不是用这些值所在的地址计算。

我建议使用offsetof,它是为您的用例而构建的。