1

我知道 C++11 有一些标准工具可以从未对齐的内存中获取整数值。这样的东西怎么能用更标准的方式来写呢?

template <class R>
inline R get_unaligned_le(const unsigned char p[], const std::size_t s) {
    R r = 0;
    for (std::size_t i = 0; i < s; i++)
        r |= (*p++ & 0xff) << (i * 8); // take the first 8-bits of the char
    return r;
}

要获取以小端顺序存储的值,您可以编写:

uint_least16_t value1 = get_unaligned_le<uint_least16_t > (&buffer[0], 2);
uint_least32_t value2 = get_unaligned_le<uint_least32_t > (&buffer[2], 4);
4

2 回答 2

1

与往常一样,创建所需的变量并按字节填充它:

#include <algorithm>
#include <type_traits>

template <typename R>
R get(unsigned char * p, std::size_t len = sizeof(R))
{
    assert(len >= sizeof(R) && std::is_trivially_copyable<R>::value);

    R result;
    std::copy(p, p + sizeof(R), static_cast<unsigned char *>(&result));
    return result;
}

这仅适用于普通可复制类型,但如果您有其他地方的额外保证,您可能可以将其用于普通类型。

于 2012-08-02T09:03:19.000 回答
1

积分值是如何进入未对齐内存的?如果它们被memcpy编入,那么您可以使用memcpy它们来取出它们。如果它们是从文件或网络中读取的,您必须知道它们的格式:它们是如何编写的。如果它们是 4 字节 big-endian 2s 补码(通常的网络格式),则类似于:

//      Supposes native int is at least 32 bytes...
unsigned
getNetworkInt( unsigned char const* buffer )
{
    return buffer[0] << 24
        |  buffer[1] << 16
        |  buffer[2] <<  8
        |  buffer[3];
}

这适用于任何无符号类型,只要您的目标类型至少与您输入的类型一样大。对于签名,这取决于您想要的便携性。如果您所有的潜在目标机器都是 2 的补码,并且将具有与您的输入类型大小相同的整数类型,那么您可以使用与上面完全相同的代码。如果您的本机机器是 1 的补码 36 位机器(例如 Unisys 大型机),并且您正在读取带符号的网络格式整数(32 位 2 的补码),您将需要一些额外的逻辑。

于 2012-08-02T09:25:35.517 回答