我正在寻找读取存储在二进制文件中的数值的最快方法。
我已经完成了一些似乎有用的功能,但我想得到关于我的实现是否良好的反馈。
以下是我从4字节小端块获取有符号整数的方法:
signed long int from4li(char const * const buffer)
{
signed long int value = 0;
value += (unsigned char) buffer[3];
value <<= 8;
value += (unsigned char) buffer[2];
value <<= 8;
value += (unsigned char) buffer[1];
value <<= 8;
value += (unsigned char) buffer[0];
return value;
}
这也适用于无符号整数,但我最初为无符号整数做了一个不同的实现(失败的有符号整数,我不知道为什么):
unsigned long int fromu4li(char const * const buffer)
{
unsigned long int value = 0;
value += (unsigned char) buffer[0] << 8 * 0;
value += (unsigned char) buffer[1] << 8 * 1;
value += (unsigned char) buffer[2] << 8 * 2;
value += (unsigned char) buffer[3] << 8 * 3;
return value;
}
我更确定从整数到小端字符串缓冲区的转换,我认为可能无法进一步优化:
void to4li(long int const value, char * const buffer)
{
buffer[0] = value >> 8 * 0;
buffer[1] = value >> 8 * 1;
buffer[2] = value >> 8 * 2;
buffer[3] = value >> 8 * 3;
}
我也认为可以更快地使用memcpy,但是要使用memcpy我必须知道主机系统的字节顺序。
我真的不想依赖主机系统的字节序,因为我认为我的代码应该独立于主机系统的内部数据表示。
那么,这是进行转换的正确方法,还是可以改进我的功能?
答案 0 :(得分:0)
使用按位OR似乎是一个好主意,但有一些奇怪的事情:
经过测试,似乎c0
,c1
,c2
,c3
需要是无符号字符才能使此解决方案正常工作。再说一次,我不知道为什么:
例如,取为0x8080,即-3264(带符号)或32896(无符号)。
使用
char c0 = 0x80;
char c1 = 0x80;
我明白了:
uint16_t res = (c0 << 0) | (c1 << 8);
// res = 65408 ???
但是
uint16_t res = ((unsigned char) c0 << 0) | ((unsigned char) c1 << 8);
// res = 32896 ok
答案 1 :(得分:0)
一种更简单的方法,也就是避免由于对有符号整数变量进行位移而导致未定义的行为,只是按位复制数据:
int32_t get(char const * const buf)
{
int32_t result;
char * const p = reinterpret_cast<char *>(&result);
std::copy(buf, buf + sizeof result, p);
return result;
}
此代码假定数据与machien具有相同的字节序。或者,您可以使用std::copy_backward
反转字节序。
此方法取决于流数据和主机端字节顺序,因此它不如无符号整数的代数解决方案那么优雅,仅依赖于流数据。但是,由于签名整数无论如何都依赖于平台,因此这可能是一种可接受的折衷方案。
(仅供比较,对于无符号整数,我更喜欢这个与机器无关的代码:
template <typename UInt>
typename std::enable_if<std::is_unsigned<UInt>::value, UInt>::type
get_from_le(unsigned char * const buf)
{
UInt result;
for (std::size_t i = 0; i != sizeof(UInt); ++i)
result += (buf[i] << (8 * i));
return result;
}
用法:auto ui = get_from_le<uint64_t>(buf);
。
对于big-endian版本,请将[i]
替换为[sizeof(UInt) - i - 1]
。)