最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Is my understanding about undefined behavior in the following code using reinterpret_cast correct? - Stack Overflow

programmeradmin5浏览0评论

Here's some code which tries to "recreate" floats by passing through char buffer:

#include <memory.h>

#include <array>
#include <iostream>
#include <span>
#include <vector>

struct A {
  std::span<const char> GetAsSpan() const {
    return std::span{reinterpret_cast<const char*>(f_arr.data()),
                     f_arr.size() * sizeof(float)};
  }

  std::vector<char> GetAsVector() const {
    std::vector<char> vec(f_arr.size() * sizeof(float));
    for (int i = 0; i < f_arr.size(); ++i) {
      char* buffer = vec.data() + i * sizeof(float);
      memcpy(buffer, &f_arr[i], sizeof(float));
    }
    return vec;
  }

  std::array<float, 2> f_arr{0.1, 0.2};
};

void Print(const std::vector<float>& f_vec) {
  for (const auto f : f_vec) {
    std::cout << f << ' ';
  }
  std::cout << '\n';
}

int main() {
  A a;
  {
    // BLOCK 1: CORRECT
    const auto sp = a.GetAsSpan();
    // The original backing array is actually of floats, so reinterpret_cast
    // should work.
    std::vector<float> f_vec1;
    const size_t n_elems1 = sp.size() / sizeof(float);
    for (auto i = 0u; i < n_elems1; ++i) {
      const char* buffer = sp.data() + i * sizeof(float);
      const float v = *reinterpret_cast<const float*>(buffer);
      f_vec1.push_back(v);
    }
    Print(f_vec1);
  }
  {
    // BLOCK 2: UNDEFINED BEHAVIOR
    const auto vec = a.GetAsVector();
    // The original backing array is "NOT" floats, so reinterpret_cast should
    // be UB.
    std::vector<float> f_vec2;
    const size_t n_elems2 = vec.size() / sizeof(float);
    for (auto i = 0u; i < n_elems2; ++i) {
      const char* buffer = vec.data() + i * sizeof(float);
      // UB:
      const float v = *reinterpret_cast<const float*>(buffer);
      f_vec2.push_back(v);
    }
    Print(f_vec2);
  }
  {
    // BLOCK 3: CORRECT
    const auto vec = a.GetAsVector();
    std::vector<float> f_vec3;
    const size_t n_elems2 = vec.size() / sizeof(float);
    for (auto i = 0u; i < n_elems2; ++i) {
      const char* buffer = vec.data() + i * sizeof(float);
      float v = 0.f;
      // memcpy should remove the UB.
      memcpy(&v, buffer, sizeof(float));
      f_vec3.push_back(v);
    }
    Print(f_vec3);
  }
}

I wanted to confirm that:

  • BLOCK 1: The reinterpret_cast to float over here is correct, since the original backing array is of type float.
  • BLOCK 2: The reinterpret_cast over here is "incorrect" (undefined behavior, if that value "v" is accessed later), since the original backing vector is of type char.
  • BLOCK 3: The memcpy being used removes the undefined behavior which was showing in BLOCK 2.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论