Pythonに存在するのと同じようstruct.pack
に、C++にある数値からの固定長の文字列が必要です。私は考えましたがitoa (i,buffer,2)
、問題はその長さがプラットフォームに依存することです。プラットフォームから独立させる方法はありますか?
4 に答える
Python の struct パッケージに似た完全なソリューションを探している場合は、Google の Protocol Buffers Libraryを調べてください。これを使用すると、多くの問題 (エンディアン性、言語の移植性、バージョン間の互換性など) に対処できます。
typedefを介して正確な幅の整数型を定義する必要があります。これは、プラットフォーム固有の方法で行います。C99を使用する場合は、int16_t
で事前定義されてい<stdint.h>
ます。次に、その型にキャストして、変数のメモリ表現を入力できます。
int16_t val = (int16_t) orig_val;
void *buf = &val;
エンディアンに対処する必要があることに注意してください。
C99がない場合は、コンパイル時または実行時のサイズテストを使用できます。コンパイル時のテストでは、さまざまなプリミティブ型のサイズをすでに計算しているautoconfの使用を検討してください。これにより、コンパイル時に適切な型を選択できます。実行時に、一連のsizeofテストを実行します。テストは常に同じ結果になるため、これは実行時にいくらか不適切であることに注意してください。autoconfの代わりに、コンパイル時のテストにコンパイラ/システム識別マクロを使用することもできます。
ここから始めましょう:
typedef std::vector<uint8_t> byte_buffer;
template <std::size_t N>
void append_fixed_width(byte_buffer& buf, uintmax_t val) {
int shift = ((N - 1) * 8);
while (shift >= 0) {
uintmax_t mask = (0xff << shift);
buf.push_back(uint8_t((val & mask) >> shift));
shift -= 8;
}
}
template <typename IntType>
void append_bytes(byte_buffer& buf, IntType val) {
append_fixed_width<sizeof(IntType)>(buf, uintmax_t(val));
}
int main() { // usage example
byte_buffer bytes;
append_bytes(bytes, 1); // appends sizeof(int) bytes
append_bytes(bytes, 1ul); // appends sizeof(unsigned long) bytes
append_bytes(bytes, 'a'); // appends sizeof(int) bytes :p
append_bytes(bytes, char('a')); // appends 1 byte
return 0;
}
Append_bytes
を使用して表されるバイト バッファに任意の整数型を追加しますstd::vector<uint8_t>
。値はビッグ エンディアンのバイト順でパックされます。これを変更する必要がある場合は、微調整append_fixed_width
して値を別の順序でトラバースします。
これらの関数は raw バイト バッファを構築するため、それをデコードする人は、そこに何があるかを知る責任があります。IIRC、これstruct.pack
も同様です。つまり、の呼び出し元はstruct.unpack
同じフォーマット文字列を提供する必要があります。代わりにTLVappend_fixed_width
をパックするバリアントを記述できます。
template <typename TagType, typename ValueType>
void append_tlv(byte_buffer& buf, TagType t, ValueType val) {
append_fixed_width<sizeof(TagType)>(buf, uintmax_t(t));
append_fixed_width<sizeof(std::size_t)>(buf, uintmax_t(sizeof(ValueType)));
append_fixed_width<sizeof(ValueType)>(buf, uintmax_t(val));
}
しかし、私はジェレミーの提案を真剣に見ていきます. 私が今持っているすべてのバイナリ パッキング コードを書いたときに、それが存在していたらよかったのにと思います。
C ++の方法は、次を使用することstringstream
です。
stringstream ss;
int number=/*your number here*/;
ss<<number;
使用するバッファを取得しますss.str().c_str()
。