打破严格的混叠,并活着讲述它

Breaking strict aliasing and living to tell about it?

本文关键字:活着 讲述      更新时间:2023-10-16

我试图在我用c++ 11编写的同一应用程序中使用两个库,LIBSVM和LIBLINEAR。LIBSVM和LIBLINEAR的输入本质上都是基于行的稀疏矩阵表示:有节点结构

struct svm_node
{
    int index;
    double value;
};

,稀疏矩阵本身就是struct svm_node **,其中每一行都是struct svm_node *,行以index = -1结束。这个结构体的线性版本称为feature_node,具有相同的定义。虽然LIBSVM和LIBLINEAR是由同一作者编写的,但svm.hlinear.h,因此struct svm_nodestruct feature_node没有任何关系。

在某些情况下,我想为我的数据创建一个内核SVM模型(仅由LIBSVM实现)和一个逻辑回归模型(仅由LIBLINEAR实现)。数据集以各自的——在二进制级别上,相同的——稀疏矩阵表示传递给库,可能相当大,我宁愿避免对其进行memcpy()处理。一个简单的reinterpret_cast<feature_node **>(svm_node_ptr_ptr_variable)似乎可以很好地完成这项工作。

我也在发布版本中使用LLVM的全程序优化(-flto),所以我想确保代码不会以不可预测的方式进行优化。

是否有任何方法将svm_node **类型双关到feature_node **,以避免可能由(当前或将来)编译器优化引起的任何损坏?__attribute__((__may_alias__))在这里有帮助吗?如果有,我应该如何使用它?


如果__attribute__((__may_alias__))只对类型有意义,如果我创建自己的结构体和指向结构体的指针,它会起作用吗

struct __attribute__((__may_alias__)) SparseElement {
    int index;
    double value;
};
typedef SparseRow SparseElement * __attribute__((__may_alias__));

然后将retinterpret_cast ed SparseRow *传递给LIBSVM和LIBLINEAR?

该结构体的线性版本称为feature_node,具有相同的定义。

如果你使用联合,你就是黄金。c++特别允许(第9.2节)访问"公共初始子序列"。

如果一个标准布局联合包含两个或多个共享公共初始序列的标准布局结构体,并且如果标准布局联合对象当前包含这些标准布局结构体中的一个,则允许检查其中任何一个的公共初始部分。如果对应的成员具有与布局兼容的类型,并且两个成员都不是位域或,则两个标准布局结构共享一个公共初始序列对于包含一个或多个初始成员的序列,它们都是具有相同宽度的位域。

即使是指针上的reinterpret_cast也可以正常工作,因为经历左值到右值转换的类型正是存在于该内存中的对象的类型。