代码之家  ›  专栏  ›  技术社区  ›  Iter Ator

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

  •  1
  • Iter Ator  · 技术社区  · 4 年前

    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;
    }
    

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

    2 回复  |  直到 4 年前
        1
  •  1
  •   Quimby    4 年前

    我看不到位置 new 在代码中,使 reinterpret_cast 只有在给定地址存在指定类型的对象时,才能取消对返回指针的引用。 char , std::byte unsigned 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;
    }
    

        2
  •  1
  •   Adrian Mole Chris    4 年前

    strict aliasing rules ,你可以使用 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;
    }
    

    从(第二个)链接的参考页:

    其中,严格的别名禁止检查与的值相同的内存 std::memcpy