C如何读取中间位?
C how to read middle bits?
请注意我的评论,问题仍未得到解答。
我有以下无法更改:
unsigned long addr=142;
u16 offset_low, offset_middle;
u32 offset_high;
我想为addr
的低16位设置offset_low
,中16位设置offset_middle
,高32位设置offset_high
。
所以我写道:
offset_low = addr & 0xFFFF;
offset_middle = addr & 0xFFFF0000;
offset_high = addr & 0xFFFFFFFF0000;
这样对吗?有什么明确的方法可以代替写那么多 F 吗?
为什么我觉得不对?
我正在使用 little endian,所以在执行 addr & 0xFFFF0000 时;我将得到中间位但带有零,它可能会加载零而不是非零。
为了您的目的,您必须移动屏蔽值:
unsigned long addr = 142; // 64-bit on the target system
uint16_t offset_low = addr & 0xFFFF;
uint16_t offset_middle = (addr & 0xFFFF0000) >> 16;
uint32_t offset_high = (addr & 0xFFFFFFFF00000000) >> 32;
请注意,由于您恰好将 16 位和 32 位提取到具有相同大小的变量,因此可以省略掩码:
uint64_t addr = 142;
uint16_t offset_low = addr;
uint16_t offset_middle = addr >> 16;
uint32_t offset_high = addr >> 32;
内存中的字节顺序(小端与大端)与这个问题无关。您可以使用这些知识从内存中读取特定部分,读取 offset_low
的前 2 个字节,offset_middle
的后 2 个字节和 offset_high
的下 4 个字节,但从完整的 64 个字节中提取-bit 值对两种体系结构执行相同。
按所需位移动 1,然后减去 1 将得到位序列 1
,除非您希望整数类型中的最高(最高)位为 1。
假设环境中的unsigned long
有33位以上,可以这样写:
offset_low = addr & ((1UL << 16) - 1);
offset_middle = (addr >> 16) & ((1UL << 16) - 1);
offset_high = (addr >> 32) & ((1UL << 32) - 1);
Is this right?
不完全是,这些是正确的:
offset_low = addr & 0xFFFF;
offset_middle = (addr >> 16) & 0xFFFF;
offset_high = addr >> 32;
您没有将结果向右移动(而您的高点恰恰是错误的)。
I am working with little endian, so when doing addr & 0xFFFF0000; I will get the mid bits but with zeros and it may load the zeros instead of non-zeroes.
字节序在代码中无关紧要,因为代码在同一台机器上运行。它只在序列化期间很重要,在序列化期间,您在一台机器上写入流并从另一台机器读取另一种字节序,从而产生垃圾。
请注意我的评论,问题仍未得到解答。
我有以下无法更改:
unsigned long addr=142;
u16 offset_low, offset_middle;
u32 offset_high;
我想为addr
的低16位设置offset_low
,中16位设置offset_middle
,高32位设置offset_high
。
所以我写道:
offset_low = addr & 0xFFFF;
offset_middle = addr & 0xFFFF0000;
offset_high = addr & 0xFFFFFFFF0000;
这样对吗?有什么明确的方法可以代替写那么多 F 吗?
为什么我觉得不对?
我正在使用 little endian,所以在执行 addr & 0xFFFF0000 时;我将得到中间位但带有零,它可能会加载零而不是非零。
为了您的目的,您必须移动屏蔽值:
unsigned long addr = 142; // 64-bit on the target system
uint16_t offset_low = addr & 0xFFFF;
uint16_t offset_middle = (addr & 0xFFFF0000) >> 16;
uint32_t offset_high = (addr & 0xFFFFFFFF00000000) >> 32;
请注意,由于您恰好将 16 位和 32 位提取到具有相同大小的变量,因此可以省略掩码:
uint64_t addr = 142;
uint16_t offset_low = addr;
uint16_t offset_middle = addr >> 16;
uint32_t offset_high = addr >> 32;
内存中的字节顺序(小端与大端)与这个问题无关。您可以使用这些知识从内存中读取特定部分,读取 offset_low
的前 2 个字节,offset_middle
的后 2 个字节和 offset_high
的下 4 个字节,但从完整的 64 个字节中提取-bit 值对两种体系结构执行相同。
按所需位移动 1,然后减去 1 将得到位序列 1
,除非您希望整数类型中的最高(最高)位为 1。
假设环境中的unsigned long
有33位以上,可以这样写:
offset_low = addr & ((1UL << 16) - 1);
offset_middle = (addr >> 16) & ((1UL << 16) - 1);
offset_high = (addr >> 32) & ((1UL << 32) - 1);
Is this right?
不完全是,这些是正确的:
offset_low = addr & 0xFFFF;
offset_middle = (addr >> 16) & 0xFFFF;
offset_high = addr >> 32;
您没有将结果向右移动(而您的高点恰恰是错误的)。
I am working with little endian, so when doing addr & 0xFFFF0000; I will get the mid bits but with zeros and it may load the zeros instead of non-zeroes.
字节序在代码中无关紧要,因为代码在同一台机器上运行。它只在序列化期间很重要,在序列化期间,您在一台机器上写入流并从另一台机器读取另一种字节序,从而产生垃圾。