【发布时间】:2011-12-16 08:36:24
【问题描述】:
u_char ip_vhl; /* version << 4 | header length >> 2 */
我做错了,这是怎么做到的? 你能给我举例说明如何使用这个字节来存储这两个数字吗 知道每个都是 4 位的
【问题讨论】:
u_char ip_vhl; /* version << 4 | header length >> 2 */
我做错了,这是怎么做到的? 你能给我举例说明如何使用这个字节来存储这两个数字吗 知道每个都是 4 位的
【问题讨论】:
如果每个数字都是 4 位,您将使用字符的最低 8 位。在许多情况下,这将是所有的位。
这样做:
ip_vhl = ((version & 15) << 4) | (length & 15);
假设version 是你想要的高位,length 是你想要的低位。 & 15 确保每个值只有 4 位。 length 值最需要这点,以避免在长度大于 15 时覆盖专用于 version 的位。十进制常量 15 将以十六进制写入(如 0xf 或 0x0f)很多人,你觉得更干净是风格和品味的问题。
另一种写“一个最右边 n 位设置为 1,所有其他位设置为 0 的整数”的方式是 ((1 << n) - 1),因为这里是 n = 4,我们可以使用 ((1 << 4) - 1),它当然会计算到15。
为了清楚起见,您的代码似乎首先将 length 划分并存储,如果您想要这样做,您应该在将其打包到单个 char 之前执行它:
length >>= 2; /* Convert from bytes to 32-bit words (or whatever). */
ip_vhl = ((version & 15) << 4) | (length & 15);
【讨论】:
版本 (a) 使用位域
struct entry {
unsigned char version : 4;
unsigned char length : 4;
} ip_vhl;
ip_vhl.version = version;
ip_vhl.length = length;
版本 (b) 算术
ip_vhl = (version << 4) | (length & 0xF)
version = ip_vhl >> 4;
length = ip_vhl & 0xf;
【讨论】:
ip_vhl = (version << 4) | (headerlen & 0xf);
那么字节会是这样的:
VVVVHHHH
要取回原始值:
version = ip_vhl >> 4;
headerlen = ip_vhl & 0xf;
【讨论】:
// Here we are trusting that version and length are both < 0xF
unsigned char ip_vhl = (unsigned char)version << 4 | (unsigned char)length;
unsigned char version = ip_vhl >> 4;
unsigned char length = ip_vhl & 0xF;
【讨论】:
此外,您还可以使用带有位域的结构:
typedef struct s_ip_vhl
{
int version : 4;
int header_length : 4;
} ip_vhl_type;
ip_vhl_type my_ip_vhl;
my_ip_vhl.version = 4;
my_ip_vhl.header_length = 5;
unsigned char byte = *((byte*)(&my_ip_vhl));
或者您可以将结构与带有 unsigned char 的 union 一起打包,以一次性获取整个字节:
typedef union u_ip_vhl
{
typedef struct s_ip_vhl
{
int version : 4;
int header_length : 4;
} ip_vhl_type;
unsigned char byte;
} ip_vhl_union;
【讨论】: