其结构位域的内存布局 [英] Memory layout of struct having bitfields
问题描述
我有这样的C结构:(重新presenting一个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("\n");
}
}
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;
}
我得到这样的输出:
I get this output:
00000000 01010100
00000000 00011100
00000000 00000001
00000000 00000000
00010001 00000100
00000000 00000000
00001110 00000101
00001010 00001100
00000111 00001001
00001100 00000110
但我希望这样的:
But I expect this:
输出是部分正确的;某处,字节和半字节似乎互换。是有一些问题的字节顺序在这里?有位字段用于此目的不是很好吗?我真的不知道。任何帮助吗?在此先感谢!
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.
这是一般不要使用要控制得到的布局,除非你有数据位域是一个好主意(编译器特定的)手段,如的#pragma
S,这样做。
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 #pragma
s, 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屋!