我有一个 C++ 程序,将 TCP 标头表示为结构:
#include "stdafx.h"
/* TCP HEADER
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct { // RFC793
WORD wSourcePort;
WORD wDestPort;
DWORD dwSequence;
DWORD dwAcknowledgment;
unsigned int byReserved1:4;
unsigned int byDataOffset:4;
unsigned int fFIN:1;
unsigned int fSYN:1;
unsigned int fRST:1;
unsigned int fPSH:1;
unsigned int fACK:1;
unsigned int fURG:1;
unsigned int byReserved2:2;
unsigned short wWindow;
WORD wChecksum;
WORD wUrgentPointer;
} TCP_HEADER, *PTCP_HEADER;
int _tmain(int argc, _TCHAR* argv[])
{
printf("TCP header length: %d\n", sizeof(TCP_HEADER));
return 0;
}
如果我运行这个程序,我会得到这个标头的大小为 24 字节,这不是我期望的大小。如果我将字段“wWindow”的类型更改为“unsigned int wWindow:16”(它与 unsigned Short 具有相同的位数),则程序会告诉我该结构的大小现在是 20 字节,这是正确的大小。为什么是这样?
我在 32 位 x86 计算机上使用 Microsoft Visual Studio 2005 SP1。
因为编译器将您的位域打包为 32 位 int,而不是 16 位实体。
一般来说,您应该避免位字段并使用其他清单常量(枚举或其他)以及显式位掩码和移位来访问字段中的“子字段”。
这是应该避免使用位域的原因之一 - 即使对于同一平台,它们在编译器之间也不是很可移植。来自C99标准(C90标准中有类似的措辞):
一个实现可以分配任何
足够大的可寻址存储单元
保存一个位域。如果空间足够
仍然是一个位字段,立即
跟随另一个位字段
结构应打包成
同一单元的相邻位。如果
剩余空间不足,是否
不适合的位域被放入
进入下一个单元或重叠
相邻单位是
实现定义的。的顺序
单元内位域的分配
(高位到低位或低位
到高阶)是
实现定义的。对齐方式
可寻址存储单元的数量为
未指定。
您无法保证位域是否会“跨越”int 边界,也无法指定位域是从 int 的低端还是从 int 的高端开始(这与处理器是否大端或小端)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)