简体   繁体   中英

Buffer filled with different types of data, and strict aliasing

According to the standard , it is always undefined behavior in C++ to make, for example, a float* point to the same memory location as a int* , and then read/write from them.

In the application I have, there can be a buffer filled with 32-bit integer elements, that are overwritten by 32-bit floating point elements. (It actually contains a representation of an image, that gets transformed in multiple stages by GPU kernels, but there should also be a host implementation that does the same processing, for verification.)

The program basically does this (not actual source code):

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]);

Is there a way to make the reinterpret_cast pointer cases well-defined, within the C++ standard, without doing additional memory copies of the whole buffer, or additional per-element copies (for example with std::bit_cast )?

Even though I wished all the time there would be a nice way, currently there is non. You will have to use no-strict-aliasing flag of the compiler of your choice.

For std::bit_cast you will have to wait until C++20 . There is no standard conform way without using memcpy as far as I know.

Also have a look at this bit_cast proposal and this website .

How about using a union? For example:

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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM