我想要一个数字中的固定长度字符串,就像struct.pack
在 python 中但在 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
以以不同的顺序遍历该值。
这些函数构建了一个原始字节缓冲区,因此无论是谁在解码它都有责任知道里面有什么。IIRC,这也是struct.pack
如此;换句话说,调用者struct.unpack
需要提供相同的格式字符串。您可以编写一个变体append_fixed_width
来打包TLV:
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));
}
不过,我会认真考虑Jeremy 的建议。我希望当我编写我现在拥有的所有二进制打包代码时它就已经存在。
C++ 方法是使用stringstream
:
stringstream ss;
int number=/*your number here*/;
ss<<number;
并获取您要使用的缓冲区ss.str().c_str()
。