我正在尝试编写一个函数,该函数接受N个字节的小字节十六进制并使其成为无符号整数。
unsigned int endian_to_uint(char* buf, int num_bytes)
{
if (num_bytes == 0)
return (unsigned int) buf[0];
return (((unsigned int) buf[num_bytes -1]) << num_bytes * 8) | endian_to_uint(buf, num_bytes - 1);
}
但是,返回的值比预期值大约约256倍。那是为什么?
如果我需要将它用于4字节缓冲区,通常你会这样做:
unsigned int endian_to_uint32(char* buf)
{
return (((unsigned int) buf[3]) << 24)
| (((unsigned int) buf[2]) << 16)
| (((unsigned int) buf[1]) << 8)
| (((unsigned int) buf[0]));
}
哪个应该由我写的递归函数重现,还是有一些我没有被捕获的算术错误?
答案 0 :(得分:0)
以下代码段可行。
unsigned int endian_to_uint(unsigned char* buf, int num_bytes)
{
if (num_bytes == 0)
return (unsigned int) buf[0];
return (((unsigned int) buf[num_bytes -1]) << (num_bytes -1) * 8) | endian_to_uint(buf, num_bytes - 1);
}
改变1:
修改了从char*
到unsigned char *
的函数参数数据类型
原因:
对于给定的buf[] = {0x12, 0x34, 0xab, 0xcd};
当您尝试阅读buf[3]
时,buf[num_bytes -1]
会因为符号扩展而向0xffffffcd
而不仅仅0xcd
提供num_bytes-1
。有关签名扩展的详细信息,请参阅Sign Extension
更改2:
计算换档位置值时使用<ul>
<li><img src="test.img" alt=""></li>
<li><p>text</p></li>
<li><p>text2</p></li>
</ul>
<ul>
<li><p>text</p></li>
<li><img src="test.img" alt=""></li>
<li><p>text2</p></li>
</ul>
。这是计算要移位的位数的逻辑错误。
答案 1 :(得分:0)
这里绝对没有理由使用递归:位移是最快的可用操作之一,递归是最慢的。此外,递归是危险的,难以阅读并且给出令人讨厌的峰值堆栈消耗。一般情况下应该避免。
此外,您的功能不是一般的功能,因为您返回unsigned int
,使功能在每一种方式都不如移位版本。
要实际编写一个通用大小的小端转换函数,你可以这样做:
void little_endian (size_t bytes, uint8_t dest[bytes], const uint8_t src[bytes])
{
for(size_t i=0; i<bytes; i++)
{
dest[i] = src[bytes-i-1];
}
}
工作示例:
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
void little_endian (size_t bytes, uint8_t dest[bytes], const uint8_t src[bytes])
{
for(size_t i=0; i<bytes; i++)
{
dest[i] = src[bytes-i-1];
}
}
int main (void)
{
uint8_t data [] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
uint32_t u32;
uint64_t u64;
little_endian(4, (uint8_t*)&u32, data);
little_endian(8, (uint8_t*)&u64, data);
printf("%"PRIx32"\n", u32);
printf("%"PRIx64"\n", u64);
return 0;
}