如何重新解释强制转换数组,这样做安全吗?

时间:2019-02-06 20:23:03

标签: c++

import io

temp = """
"fullName": "Markus Graham",
"headline": "CEO ",
"company": "Orange",
"school": "Oxford ",
"location": "England",
"fullName": "Peter Hallsen",
"headline": "Co-Founder",
"company": "Telecom",
"school": "Cambridge ",
"location": "null"
"""
df = pd.read_csv(io.StringIO(temp), sep = ':', header = None, names = ['column', 'value'])

df['tmp'] = (df['column']=='fullName').cumsum()

new_df = df.pivot(columns = 'column', index = 'tmp',  values = 'value').reset_index(drop = True).replace('"|,', '', regex = True)

new_df.columns.name = None


    company fullName        headline    location    school
0   Orange  Markus Graham   CEO         England     Oxford
1   Telecom Peter Hallsen   Co-Founder  null        Cambridge

我想将其重新解释为Box数组,其中每个box包含4个点的数组。每个点都包含2个浮点数,(x,y)

// this boxes8a contains a flat array of floats
// There are n boxes and the array is n * 8 long
float* boxes8a = ...;

问题1:如何将struct Box { point points[4] } struct point { float x, y } 投射到Box数组中?

Q2:这样做是一种好习惯吗?

3 个答案:

答案 0 :(得分:3)

  

问题1:如何将float* boxes8a投射到Box数组中?

这不是您应该通过强制转换解决的问题。 float*Box是不同的东西。它们可能都是用浮点数构建的,但是它们没有关联,因此不能相互转换,因为这将是严格的别名冲突。

  

Q2:这样做是一种好习惯吗?

不。如上所述,您不允许这样做。

但是,您可以使用std::memcpyfloat数组的值复制到Box数组中。看起来像

float* boxes8a = some_data;
Box array[correct_size];
static_asset(sizeof(Box) == sizeof(float) * 8, "data sizes are incompatible");
std::memcpy(array, boxes8a, correct_size);

答案 1 :(得分:2)

  

如何将float* boxes8a转换为Box的数组?

危险地。

//Undefined Behavior, might not do what you want it to do!
Box* boxes = reinterpret_cast<Box*>(boxes8a); 
  

这样做是一种好习惯吗?

否。

在C ++中,这被视为未定义行为,尽管许多编译器会为您提供看起来像它们可以工作的结果,但是我不能建议这样做。最好的解决方案是将值简单复制到Box对象中,然后让这些对象拥有自己的数据。

std::vector<Box> boxes(n);
for(size_t i = 0; i < n; i++) {
    for(int j = 0; j < 4; j++)
        boxes[i][j] = point{boxes8a[i*8 + j*2 + 0], boxes8a[i*8 + j*2 + 1]};
}

或者,冒着听起来像是面向数据设计的 Cultists 支持者之一的风险,您可能会考虑让Box对象仅包含指向对象中某个位置的指针。数据开始的数组:

class point {
    float* data;
public:
    point(float* data) : data(data) {}

    float& x() const {return *data;}
    float& y() const {return *(data+1);}
};

class Box {
    float* data;
public:
    Box(float* data) : data(data) {}

    point operator[](size_t index) const {
        return point(data + index * 2);
    }
};

int main() {
    std::vector<Box> boxes;
    for(size_t i = 0; i < n; i++)
        boxes.emplace_back(boxes8a + i*8);

    boxes[3][3].x() = 34.7; //Will alter the original value in boxes8a!
}

此方法将允许Box对象对原始float*数组进行别名而不破坏别名规则。

答案 2 :(得分:0)

  

Q1:如何将float * box8a转换为Box数组?

Box* boxes = std::reinterpret_cast<Box*>(boxes8a);
  

Q2:这样做是一种好习惯吗?

不,这是可憎的。 struct point可以在数组中的元素内部或之间填充。这是不确定的行为。请重新设计您的问题解决方案,