更新:实现在C中
我正在尝试编写一个endianess转换函数
我的理解是,两种方式的endianess转换使用相同的函数,因为它是字节反转。
我有两个实现。
方法1
在lsb处获取每个字节,并与结果进行OR运算,然后将结果左移
unsigned int convert_endian(unsigned int num)
{
unsigned int res=0;
int i = 0;
while(i < sizeof(int))
{
res = res << 8;
res |= num & 0xFF;
num = num >> 8;
i++;
}
return res;
}
字符串
方法2
使用一个字符指针来获取每个字节,并将其OR到结果中
unsigned int convert_endian_char(unsigned int num)
{
unsigned int res=0;
char *ptr = (char*)#
int i=0;
while(i<sizeof(int))
{
res = res << 8;
res |= *ptr & 0xFF;
i++;
ptr++;
}
return res;
}
型
这段代码似乎可以工作,例如:对于num = 0x12345678,我得到res = 0x78563412
但是在代码审查期间,我被告知这不起作用,而且在轮班期间,我会在方法1中丢失字节。
3条答案
按热度按时间fsi0uk1n1#
方法1的候选人问题。
所有的问题都是模糊的。
res = res << 8; res |= num & 0xFF;
在char
不是8位的机器上失败。(罕见。)如果试图交换本地定义的“字节”,则与res = res << CHAR_BIT; res |= num & UCHAR_MAX;
一样好。unsigned
既不是像PDP-11-endian那样的大字节序,也不是小字节序,那么实现交换大/小字节序的代码的正确性是值得怀疑的(非常罕见)。sizeof(char) == sizeof(unsigned)
,(非常罕见)我们会遇到麻烦,因为不需要循环-取决于目标。int i = 0; while(i < sizeof(int))
-->unsigned /* or size_t */ i = 0; while(i < sizeof(int))
。sizeof(int) == sizeof(unsigned)
并不是一个真正的问题,但最好不要在这段代码中的任何地方引入int
。没有任何内容与“在移位期间方法1中丢失字节”Assert匹配。
或许:
1.面试官 * 错误地 * 认为
res << 8
在转换到符号位时会导致UB(未定义的行为)。然而,由于unsigned
,没有符号位,也没有UB。num = num >> 8;
破坏了num
的原始值。但那又怎样?num
不需要保存。1.采访者故意用一个没有证据的说法来挑战OP,以评估OP如何处理它。
1.发布的代码与面试中的代码并不完全相同。令人惊讶的是,即使是一个字符的差异也意味着很多。
我怀疑是3或4个。
备选方案:
字符串
除了@John Bollinger和
char *ptr
之外,没有评论方法2,因为unsigned char *ptr
更好地处理各种 * 有符号 * 编码。我的理解是,两种方式的endianess转换使用相同的函数,因为它是字节反转。
对于big/little endian为真,但其他endian也是可能的。
lztngnrs2#
不需要考虑太多。像这样的东西应该在大/小端之间是可移植的:
字符串
gcc 12.3 -O3:
型
应该有点符合MISRA,适合小型微控制器等。
gjmwrych3#
似乎,在普通的内存中,一个内存地址可以存储1个字节的内容.
所以要转换endian(在big和little之间),你不需要做任何按位的操作,只要把你的原始类型处理成byte数组,然后反转它,就可以了。
字符串