将指向结构的指针转换为另一个具有较少字段数的结构类型

时间:2017-04-05 18:18:13

标签: c++ pointers reflection struct reinterpret-cast

基本问题

我处在一个棘手的情况,需要获取指向结构mainset的指针并将其转换为指向结构subset的指针,其结构是{{1}字段的连续子集。 1}},从第一个开始。有这样的事情,有明确的行为吗?我意识到这是一件非常可怕的事情,但我有很好的和令人沮丧的理由[在患者读者的底部解释]。

我尝试使用clang编译器在OS X上实现似乎

mainset

正如我所料,输出确实为1。但是,我想知道:我只是对一个特定的编译器和一个简单的案例(实际上我的结构更复杂)感到幸运,或者这通常会起作用吗?

此外,一个后续问题:出于其他恼人的原因,我担心我可能需要制作更大的结构

#include <iostream>

struct mainset {
    size_t size;
    uint32_t reflex_size;
};

struct subset {
    size_t size;
};

using namespace std;
int main(int argc, char *argv[]) {
    mainset test = {1, 1};
    subset* stest = reinterpret_cast<subset*>(&test);
    std::cout << stest->size << std::endl;
}

相反,额外的字段在前面。在这种情况下,我的实施可以延伸到工作吗?我尝试用struct mainset { uint32_t reflex_size; size_t size; }; 替换&test,但这不起作用; &test+sizeof(test.reflex_size)语句的输出为0。

解释我必须这样做的原因

我的项目使用GSL库进行线性代数。该库使用了

形式的结构
cout

struct gsl_block { size_t size; double* data; } gsl_vector等类似结构。所以,我已经将这些结构用作我的C ++类的成员;没问题。但是,我项目最近要求的功能是使用Reflex工具(ROOT生态系统的一部分)对我的课程进行反思。要在Reflex中为这样的结构启用反射,我必须添加注释,如

gsl_matrix

此注释告诉Reflex数组的长度由同一结构的字段struct gsl_block { size_t size; double* data; //[size] } 提供。通常情况下, Reflex和ROOT有一个非常不幸的限制:长度字段必须是32位。在被告知此限制不会很快得到解决,并且没有时间/资源来自行修复它,我正在寻找解决方法。我的想法是以某种方式在更大的结构中嵌入与size位兼容的结构:

gsl_block

以及struct extended_gsl_block { size_t size; double* data; //[reflex_size] uint32_t reflex_size; } gsl_vector的类似内容;我可以确保gsl_matrixreflex_size始终相等(两者都不大于~50)并且Reflex将能够正确解析此标头(我希望;如果需要reflex_size在数据之前作为a在需要更困难的领域)。由于GSL例程使用指向这些结构的指针,我的想法是这样的:给定一个指针size,以某种方式获得指向仅extended_gsl_block*sizedata字段的指针进入reinterpret_cast

1 个答案:

答案 0 :(得分:2)

你很幸运。

您作为示例显示的类符合标准布局类型的要求。

您可以在这里阅读更多内容:

http://en.cppreference.com/w/cpp/language/data_members#Standard_layout

您可以使用以下命令在编译器中测试此前提:

static_assert(std::is_standard_layout<gsl_block>::value, "not a standard layout");