缓冲区填充不同类型的数据,并严格别名
Buffer filled with different types of data, and strict aliasing
根据 the standard,在 C++ 中总是未定义的行为,例如,使 float*
指向与 int*
相同的内存位置,然后 read/write 来自他们。
在我的应用程序中,可以有一个填充了 32 位整数元素的缓冲区,这些元素被 32 位浮点元素覆盖。 (它实际上包含图像的表示,由 GPU 内核在多个阶段进行转换,但也应该有一个执行相同处理的主机实现,以供验证。)
程序基本上是这样做的(不是实际的源代码):
void* buffer = allocate_buffer(); // properly aligned buffer
static_assert(sizeof(std::int32_t) == sizeof(float), "must have same size");
const std::int32_t* in = reinterpret_cast<const std::int32_t*>(buffer);
float* out = reinterpret_cast<float*>(buffer);
for(int i = 0; i < num_items; ++i)
out[i] = transform(in[i]);
有没有办法在 C++ 标准中明确定义 reinterpret_cast
指针情况,而无需对整个缓冲区进行额外的内存复制,或额外的每个元素复制(例如 std::bit_cast
)?
尽管我一直希望有一个好的方法,但目前没有。您将必须使用您选择的编译器的 no-strict-aliasing
标志。
对于 std::bit_cast
,您必须等到 C++20
。据我所知,不使用 memcpy
就没有符合标准的方法。
也看看这个bit_cast proposal and this website。
使用工会怎么样?例如:
union T {
std::int32_t i;
float f;
}
T* buffer = allocate_buffer();
for(int i = 0; i < num_items; ++i)
buffer[i].f = transform(buffer[i].i);
根据 the standard,在 C++ 中总是未定义的行为,例如,使 float*
指向与 int*
相同的内存位置,然后 read/write 来自他们。
在我的应用程序中,可以有一个填充了 32 位整数元素的缓冲区,这些元素被 32 位浮点元素覆盖。 (它实际上包含图像的表示,由 GPU 内核在多个阶段进行转换,但也应该有一个执行相同处理的主机实现,以供验证。)
程序基本上是这样做的(不是实际的源代码):
void* buffer = allocate_buffer(); // properly aligned buffer
static_assert(sizeof(std::int32_t) == sizeof(float), "must have same size");
const std::int32_t* in = reinterpret_cast<const std::int32_t*>(buffer);
float* out = reinterpret_cast<float*>(buffer);
for(int i = 0; i < num_items; ++i)
out[i] = transform(in[i]);
有没有办法在 C++ 标准中明确定义 reinterpret_cast
指针情况,而无需对整个缓冲区进行额外的内存复制,或额外的每个元素复制(例如 std::bit_cast
)?
尽管我一直希望有一个好的方法,但目前没有。您将必须使用您选择的编译器的 no-strict-aliasing
标志。
对于 std::bit_cast
,您必须等到 C++20
。据我所知,不使用 memcpy
就没有符合标准的方法。
也看看这个bit_cast proposal and this website。
使用工会怎么样?例如:
union T {
std::int32_t i;
float f;
}
T* buffer = allocate_buffer();
for(int i = 0; i < num_items; ++i)
buffer[i].f = transform(buffer[i].i);