如何安全地将 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
的行为都未定义。
只有在给定地址存在指定类型的对象时,才能取消引用返回的指针。 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;
}
这也解决了任何对齐问题。
为了避免可能出现的违反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.
我创建了一个字节数组,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;
}
这也解决了任何对齐问题。
为了避免可能出现的违反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.