4バイトごとに抽出する必要があるフィールドである整数のバッファ/ペイロードがあります。バッファを指すポインタがあります。ここで、バッファの最後に到達するまで、4 バイトを抽出して変数に代入する必要があります。ポインターは buf への uint8_t ポインターであり、buf は詳細がカプセル化されたバッファー オブジェクトです。これを行うための最良かつ最もエレガントな方法は何ですか? 私はc ++でコーディングしています。どんな提案でも大歓迎です。
7 に答える
バイトを 1 つずつ読み取り、数値を「手動で」組み立てることをお勧めします。これには、予想されるエンディアンを明確にする必要がありますが、これは良いことです。また、バッファから読み取るのはバイトだけであるため、アライメント要件に合わせてコードを適切に作成できます。
uint32_t extract_uint32_be(const uint8_t *buffer)
{
const uint8_t b0 = buffer[0], b1 = buffer[1], b2 = buffer[2], b3 = buffer[3];
return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
}
Cコードを使用して、次のように実行できます。
int i = 0;
int value;
while(i < buffersize)
{
value = 0;
memcpy(&value, buffer, sizeof(int));
//if the buffer is from network, then you may have to do a conversion from network order to host order here
printf("%d", value);
buffer = buffer + sizeof(int);
i = i + sizeof(int);
}
バッファ内の整数が単語で整列されている場合は、次を試すことができます。
const char* ptr; // this points to a position in a buffer
int value = reinterpret_cast<int*>(ptr);
それ以外の場合は、おそらくより安全でより望ましい:
const char* ptr;
int value;
std::copy(ptr, ptr+sizeof(int), reinterpret_cast<char*>(value));
ところで:エンディアンに問題がないことを確認してください(つまり、これが機能するには、マシンとそれらのintを保存したマシンの両方が同じエンディアンを持っている必要があります。そうでない場合は、補正する必要があります)。ここでは、C++ の特定の実装に依存しています。
assert(buf_bytes % 4 == 0);
std::vector<uint32_t> numbers(buf_bytes/4);
memcpy(&numbers[0], buf, buf_bytes);
if (need_byte_swap)
std::for_each(numbers.begin(), numbers.end(), [](uint32_t &n){ntohl(n);});
Cコードを使用して、次のように実行できます。
i は、4 バイトが読み取られるバッファーを指します。
read = (UInt32)((UInt8*)p_msg)[i++] << 24;
read |= (UInt32)((UInt8*)p_msg)[i++] << 16;
read |= (UInt32)((UInt8*)p_msg)[i++] << 8;
read |= (UInt32)((UInt8*)p_msg)[i++];
バイトを一度に 1 つずつ読み取って int にシフト/追加するか、memcpy を使用してバイトを正しい型の変数にコピーします。std::copy も受け入れられるかもしれませんが、そのエイリアスのルールはわかりません。
提案として配列にキャストすると、厳密なエイリアシング規則に違反する可能性が高いため、動作が保証されず、未定義の動作になる可能性があります。
4 バイト整数とインデックスの配列にキャストします。