正确的数据类型用于操作原始内存

And*_*rew 3 c++ c++11 c++14 c++17

我有一个便于编码/解码原始内存的类.我最终存储一个void指向内存的指针和被引用的字节数.我担心混叠问题以及位移操作以使编码正确.实质上,WHAT_TYPE我应该使用char,unsigned char,int8_t,uint8_t,int_fast8_t,uint_fast8_t,int_least8_t,或uint_least8_t?规范中是否有确定的答案?

class sample_buffer {
    size_t index; // For illustrative purposes
    void *memory;
    size_t num_bytes;
public:
    sample_buffer(size_t n) :
        index(0),
        memory(malloc(n)),
        num_bytes(memory == nullptr ? 0 : n) {
    }
    ~sample_buffer() {
        if (memory != nullptr) free(memory);
    }
    void put(uint32_t const value) {
        WHAT_TYPE *bytes = static_cast<WHAT_TYPE *>(memory);
        bytes[index] = value >> 24;
        bytes[index + 1] = (value >> 16) & 0xFF;
        bytes[index + 2] = (value >> 8) & 0xFF;
        bytes[index + 3] = value & 0xFF;
        index += 4;
    }
    void read(uint32_t &value) {
        WHAT_TYPE const *bytes = static_cast<WHAT_TYPE const *>(memory);
        value = (static_cast<uint32_t>(bytes[index]) << 24) |
                (static_cast<uint32_t>(bytes[index + 1]) << 16) |
                (static_cast<uint32_t>(bytes[index + 2]) << 8) |
                (static_cast<uint32_t>(bytes[index + 3]);
        index += 4;
    }
};
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 10

在C++ 17中:std::byte.这种类型是专门为此创建的,以传达所有正确的语义含义.此外,它具有您需要在原始数据上使用的所有运算符(如<<您的示例中所示),但没有您不需要的运算符.


在C++ 17之前:unsigned char.该标准将对象表示定义为序列unsigned char,因此它只是一个好的类型.此外,正如Mooing Duck正确地建议的那样,使用unsigned char*可以防止因错误使用你char*所引起的许多错误引用原始字节,就好像它是一个字符串并将其传递给类似的函数strlen.

如果你真的不能使用unsigned char,那么你应该使用char.这两个unsigned charchar是你被允许通过别名的类型,所以无论是优于其他任何整数类型.

  • 另外:_Please_首选`unsigned char`作为字节.我看到_far_由于在`char*`上调用`strlen`,`strcpy`或`sprintf`引起的错误太多了.`unsigned char`迫使开发人员停下来思考他们是否正在使用正确的功能. (6认同)