0

バイナリファイルに保存されている数値を読み取る最速の方法を探しています。

動作しているように見えるいくつかの機能を実行しましたが、実装が適切かどうかについてフィードバックを受け取りたいと思います。

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を使用するには、ホストシステムのエンディアンを知る必要があります。

私のコードはホストシステムの内部データ表現から独立している必要があると思うので、ホストシステムのエンディアンに依存したくありません。

それで、これはそれらの変換を行う適切な方法ですか、それとも関数を改善できますか?

4

2 に答える 2

0

ビットごとのORを使用することは良い考えのようですが、奇妙なことがあります。

テスト後、このソリューションが機能するためには、、、、、unsignedcharsc0c1ある必要があるようです。繰り返しますが、理由はわかりません。c2c3

たとえば、-3264(署名済み)または32896(署名なし)である0x8080を取り上げます。

使用する

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
于 2012-06-16T15:04:10.547 に答える
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;
}

このコードは、データがマチエンと同じエンディアンを持っていることを前提としています。または、エンディアン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);

ビッグエンディアンバージョンの場合は、に置き換え[i]ます[sizeof(UInt) - i - 1]。)

于 2012-06-16T21:10:19.127 に答える