我创建了一个字节数组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
的行为都是未定义的。只有在给定地址存在指定类型的对象时,才能取消引用返回的指针除了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;
}
这也解决了任何对齐问题。
为了避免违反严格别名规则的可能问题,可以使用std::memcpy
函数:
#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页面:
其中严格混叠禁止检查与的值相同的内存两种不同类型的
std::memcpy
可以用于转换值。