基本问题
我处在一个棘手的情况,需要获取指向结构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_matrix
和reflex_size
始终相等(两者都不大于~50)并且Reflex将能够正确解析此标头(我希望;如果需要reflex_size在数据之前作为a在需要更困难的领域)。由于GSL例程使用指向这些结构的指针,我的想法是这样的:给定一个指针size
,以某种方式获得指向仅extended_gsl_block*
和size
和data
字段的指针进入reinterpret_cast
。
答案 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");