我遇到了这段现有的C代码。我正在努力理解它。
我应该将在缓冲区中传递的4字节无符号值(小端格式)读入类型为“ long”的变量中。
这段代码在64位字长,小端x86机器上运行-其中sizeof(long)是8个字节。我的猜测是该代码还打算在32位x86机器上运行-因此,为了存储来自四字节输入数据的值,使用了long类型的变量而不是int。
我有一些疑问,并在代码中添加了注释以表达我的理解或不理解的内容:-)
请在这种情况下回答以下问题
void read_Value_From_Four_Byte_Buff( char*input)
{
/* use long so on 32 bit machine, can still accommodate 4 bytes */
long intValueOfInput;
/* Bitwise and of input buffer's byte 0 with 0xFF gives MSB or LSB ?*/
/* This code seems to assume that assignment will store in rightmost byte - is that true on a x86 machine ?*/
intValueOfInput = 0xFF & input[0];
/*left shift byte-1 eight times, bitwise "or" places in 2nd byte frm right*/
intValueOfInput |= ((0xFF & input[1]) << 8);
/* similar left shift in mult. of 8 and bitwise "or" for next two bytes */
intValueOfInput |= ((0xFF & input[2]) << 16);
intValueOfInput |= ((0xFF & input[3]) << 24);
}
我的问题
1)输入缓冲区应为“小端”。但是从代码看来,这里的假设是:字节0 = MSB,字节1,字节2,字节3 = LSB。我这样想是因为代码从字节0开始读取字节,而随后的字节(从1开始)则在左移后放置在目标变量中。是这样吗,还是我弄错了?
2)我觉得这是一种复杂的工作方式-是否有更简单的替代方法将值从4字节缓冲区复制到长变量中?
3)假设“此代码将在64位计算机上运行”会否影响我可以轻松实现此目的?我的意思是要保持单词大小不可知(是否现在不知道单词大小-尽管不确定)吗?
谢谢您的启发:-)
uint32_t x = *(uint32_t *)input;
但这是假设您的计算机为低端字节序,并且我认为根据C标准,这可能是未定义的行为。uint32_t
和int32_t
这样的类型,以便更轻松地推断您的代码是否适用于不同的体系结构。您只需要包括stdint.h
C99的标头即可使用这些类型。此函数最后一行的右侧可能会显示不确定的行为,具体取决于输入中的数据:
((0xFF & input[3]) << 24)
问题在于,这(0xFF & input[3])
将是一个有符号的int
(由于整数提升)。的int
可能会是32位的,到目前为止,你正在把它的左边所得到的值可能不是一个表示的int
。在C标准说,这是不确定的行为,你应该尽量避免,因为它使编译器许可证才能为所欲为,你将无法预测结果。
一种解决方案是将它从一个转换int
到一个uint32_t
移位它,使用流延之前。
最后,将变量intValueOfInput
写入但从未使用过。您不应该将其退还或存储在某个地方吗?
考虑到所有这些,我将这样重写函数:
uint32_t read_value_from_four_byte_buff(char * input)
{
uint32_t x;
x = 0xFF & input[0];
x |= (0xFF & input[1]) << 8;
x |= (0xFF & input[2]) << 16;
x |= (uint32_t)(0xFF & input[3]) << 24;
return x;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句