1

C++1 には、アラインされていないメモリから整数値を取得できる標準機能がいくつかあることを知っています。このようなものをより標準的な方法で書くにはどうすればよいでしょうか?

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

そもそも、積分値はどのようにして整列されていないメモリに入りましたか?それらがmemcpy編集された場合、あなたはmemcpyそれらを取り出すために使用することができます。それらがファイルまたはネットワークから読み取られた場合、それらの形式、つまり最初にどのように記述されたかを知る必要があります。それらが4バイトのビッグエンディアン2の補数(通常のネットワーク形式)である場合、次のようになります。

//      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 に答える
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 に答える