具有位域的结构的内存布局 [英] Memory layout of struct having bitfields

查看:29
本文介绍了具有位域的结构的内存布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 C 结构:(代表一个 IP 数据报)

I have this C struct: (representing an IP datagram)

struct ip_dgram
{
    unsigned int ver   : 4;
    unsigned int hlen  : 4;
    unsigned int stype : 8;
    unsigned int tlen  : 16;
    unsigned int fid   : 16;
    unsigned int flags : 3;
    unsigned int foff  : 13;
    unsigned int ttl   : 8;
    unsigned int pcol  : 8;
    unsigned int chksm : 16;
    unsigned int src   : 32;
    unsigned int des   : 32;
    unsigned char opt[40];
};

我给它赋值,然后像这样以 16 位字打印它的内存布局:

I'm assigning values to it, and then printing its memory layout in 16-bit words like this:

//prints 16 bits at a time
void print_dgram(struct ip_dgram dgram)
{
    unsigned short int* ptr = (unsigned short int*)&dgram;
    int i,j;
    //print only 10 words
    for(i=0 ; i<10 ; i++)
    {
        for(j=15 ; j>=0 ; j--)
        {
            if( (*ptr) & (1<<j) ) printf("1");
            else printf("0");
            if(j%8==0)printf(" ");
        }
        ptr++;
        printf("
");
    }
}

int main()
{
    struct ip_dgram dgram;

    dgram.ver   = 4;
    dgram.hlen  = 5;
    dgram.stype = 0;
    dgram.tlen  = 28;
    dgram.fid   = 1;
    dgram.flags = 0;
    dgram.foff  = 0;
    dgram.ttl   = 4;
    dgram.pcol  = 17;
    dgram.chksm = 0;
    dgram.src   = (unsigned int)htonl(inet_addr("10.12.14.5"));
    dgram.des   = (unsigned int)htonl(inet_addr("12.6.7.9"));

    print_dgram(dgram);

    return 0;
}

我得到这个输出:

00000000 01010100 
00000000 00011100 
00000000 00000001 
00000000 00000000 
00010001 00000100 
00000000 00000000 
00001110 00000101 
00001010 00001100 
00000111 00001001 
00001100 00000110

但我希望这样:

输出部分正确;在某处,字节和半字节似乎可以互换.这里有字节序问题吗?位域不适合这个目的吗?我真的不知道.有什么帮助吗?提前致谢!

The output is partially correct; somewhere, the bytes and nibbles seem to be interchanged. Is there some endianness issue here? Are bit-fields not good for this purpose? I really don't know. Any help? Thanks in advance!

推荐答案

不,位域不适用于此目的.布局依赖于编译器.

No, bitfields are not good for this purpose. The layout is compiler-dependant.

在要控制结果布局的数据中使用位域通常不是一个好主意,除非您有(特定于编译器的)方法,例如 #pragmas,可以这样做.

It's generally not a good idea to use bitfields for data where you want to control the resulting layout, unless you have (compiler-specific) means, such as #pragmas, to do so.

最好的方法可能是在没有位域的情况下实现这一点,即通过自己执行所需的按位运算.这很烦人,但比以某种方式挖掘解决此问题的方法要容易得多.此外,它与平台无关.

The best way is probably to implement this without bitfields, i.e. by doing the needed bitwise operations yourself. This is annoying, but way easier than somehow digging up a way to fix this. Also, it's platform-independent.

将标头定义为一个 16 位字的数组,然后您就可以很容易地计算校验和.

Define the header as just an array of 16-bit words, and then you can compute the checksum easily enough.

这篇关于具有位域的结构的内存布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆