0

我想要一个数字中的固定长度字符串,就像struct.pack在 python 中但在 c++ 中一样。我想过,itoa (i,buffer,2)但问题可能是它的长度将取决于平台。有没有办法让它独立于平台?

4

4 回答 4

4

如果您正在寻找类似于 Python 的 struct 包的完整解决方案,您可以查看Google 的 Protocol Buffers Library。使用它会为您解决很多问题(例如字节序、语言可移植性、跨版本兼容性)。

于 2009-10-11T17:43:43.540 回答
1

您需要通过 typedef 定义一个精确宽度的整数类型;您以特定于平台的方式执行此操作。如果您使用 C99,int16_t则在<stdint.h>. 然后,您可以转换为该类型,并键入变量的内存表示:

int16_t val = (int16_t) orig_val;
void *buf = &val;

请注意,您仍然需要处理字节顺序。

如果您没有 C99,则可以使用编译时或运行时大小测试。对于编译时测试,请考虑使用 autoconf,它已经计算了各种原始类型的大小,以便您可以在编译时选择一个好的类型。在运行时,只需进行一系列 sizeof 测试。请注意,这有点不适合运行时,因为测试总是会得出相同的结果。作为 autoconf 的替代方法,您还可以使用编译器/系统标识宏进行编译时测试。

于 2009-10-11T13:53:04.317 回答
1

这是一个开始:

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 的建议。我希望当我编写我现在拥有的所有二进制打包代码时它就已经存在。

于 2009-10-12T13:55:27.483 回答
0

C++ 方法是使用stringstream

stringstream ss;
int number=/*your number here*/;
ss<<number;

并获取您要使用的缓冲区ss.str().c_str()

于 2009-10-11T13:54:27.267 回答