代码之家  ›  专栏  ›  技术社区  ›  tmlen

C++类型别名,其中值被替换

  •  0
  • tmlen  · 技术社区  · 6 年前

    下面的代码在C++中合法吗?

    int get_i(int idx) { ... }
    float transform(int i) { ... }
    void use(float f) { ... }
    
    static_assert(sizeof(int) == sizeof(float));
    void* buffer = std::malloc(n * sizeof(int));
    
    int* i_buffer = reinterpret_cast<int*>(buffer);
    float* f_buffer = reinterpret_cast<float*>(buffer);
    
    // Fill int values into the buffer
    for(int idx = 0; idx < n; ++idx)
        i_buffer[idx] = get_i(idx);
    
    // Transform int value to float value, and overwrite
    // (maybe violates strict aliassing rule?)
    for(int idx = 0; idx < n; ++idx)
        f_buffer[idx] = transform(i_buffer[idx]);
    
    for(int idx = 0; idx < n; ++idx)
        use(f_buffer[idx]);
    

    第二步将缓冲区值读取为 int ,然后写入 float 取而代之。它从不通过 i_buffer 之后再重复一次,因此在读取时没有类型别名。

    但是任务 f_buffer[idx] = 浮动 对象转换为 对象,即UB。

    有没有办法让编译器认为这意味着 内景 应该结束了 浮动 对象应该在其位置构造,以便没有类型别名?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Maxim Egorushkin    6 年前

    f_buffer[idx] = 将浮点对象写入int对象,即UB。

    是的,上面的休息 type aliasing rules

    要解决这个问题,对于值,可以使用并集:

    union U {
        float f;
        int i;
    };
    

    然后访问相应的工会成员。

    这样做时:

    buffer[idx].i = ...; // make i the active union member
    ...
    buffer[idx].f = transform(buffer[idx].i); // make f the active union member
    

    buffer[idx].i buffer[idx].f