如何安全地将 int 复制到未对齐的字节数组中?

How is it possible to safely copy an int into a byte array unaligned?

我创建了一个字节数组,uint8_t data[256],我想在任意位置读取和写入数据。位置偏移量可以是任意数字,因此它可能导致未对齐的访问。例如,如果 sizeof(int32_t) == 4 那么 position % sizeof(int32_t) != 0

现在可以使用了,但是据我所知,有些平台不直接支持未对齐访问。我也想让它在那种情况下工作。

#include <cstdint>
#include <iostream>

void write(uint8_t* data, uint32_t position, int32_t value) {
    int32_t* ptr = reinterpret_cast<int32_t*>(&data[position]);
    
    *ptr = value;
}

int32_t read(uint8_t* data, uint32_t position) {
    int32_t* ptr = reinterpret_cast<int32_t*>(&data[position]);
    
    return *ptr;
}

int main()
{
    uint8_t data[256];
    int32_t value = 123456789;
    uint32_t position = 1; // Example for unaligned access

    write(data, position, value);
    
    int32_t read_value = read(data, position);
    
    std::cout << read_value << std::endl;

    return 0;
}

如果这个问题有解决方案,我更喜欢使用标准库。

我在您的代码中没有看到任何位置 new,这使得两个 reinterpret_cast 的行为都未定义。 只有在给定地址存在指定类型的对象时,才能取消引用返回的指针。 charstd::byteunsigned char 除外始终可以取消引用。

如何序列化和反序列化对象的安全方法是通过 std::memcpy:

void write(unsigned char* data, uint32_t position, int32_t value) {
   
    std::memcpy(data+position,&value,sizeof(value));
}

int32_t read(unsigned char* data, uint32_t position) { 
    int32_t result;
    std::memcpy(&result,data+position,sizeof(result));
    return result;
}

这也解决了任何对齐问题。

为了避免可能出现的违反strict aliasing rules, you can use the std::memcpy function的问题:

#include <cstring> // For std::memcpy

void write(uint8_t* data, uint32_t position, int32_t value)
{
    std::memcpy(&data[position], &value, sizeof(value));
}

int32_t read(uint8_t* data, uint32_t position)
{
    int answer;
    std::memcpy(&answer, &data[position], sizeof(answer));
    return answer;
}

来自(第二个)链接的 cppreference 页面:

Where strict aliasing prohibits examining the same memory as values of two different types, std::memcpy may be used to convert the values.