vit*_*tke 10 c++ arrays struct static-cast language-lawyer
将双数组转换为由双精度构成的结构是否可以?
struct A
{
double x;
double y;
double z;
};
int main (int argc , char ** argv)
{
double arr[3] = {1.0,2.0,3.0};
A* a = static_cast<A*>(static_cast<void*>(arr));
std::cout << a->x << " " << a->y << " " << a->z << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这打印1 2 3.但它是否保证每次都可以与任何编译器一起工作?
编辑:根据
9.2.21:指向标准布局结构对象的指针,适当转换?使用reinterpret_cast,指向其初始成员(...),反之亦然.
如果我用我的代码替换
struct A
{
double & x() { return data[0]; }
double & y() { return data[1]; }
double & z() { return data[2]; }
private:
double data[3];
};
int main (int, char **)
{
double arr[3] = {1.0,2.0,3.0};
A* a = reinterpret_cast<A*>(arr);
std::cout << a->x() << " " << a->y() << " " << a->z() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
然后它保证工作.正确?我知道很多人都不会觉得这很令人满意,但是使用结构体并且不必复制输入数组数据是有好处的.我可以在该结构中定义成员函数来计算标量和向量产品,距离等,这将使我的代码比使用数组更容易理解.
怎么样
int main (int, char **)
{
double arr[6] = {1.0,2.0,3.0,4.0,5.0,6.0};
A* a = reinterpret_cast<A*>(arr);
std::cout << a[0].x() << " " << a[0].y() << " " << a[0].z() << "\n";
std::cout << a[1].x() << " " << a[1].y() << " " << a[1].z() << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这也保证可以工作,或者编译器可以在数据成员之后添加一些内容sizeof(A) > 3*sizeof(double)吗?是否有任何可移植的方法来阻止编译器这样做?
小智 9
不,这不能保证.
从之间插入填充,禁止任何编译器的唯一的事x和y之间,或y与z是常识.任何不允许使用的语言标准都没有规则.
即使没有填充,即使表示A与其完全相同double[3],它仍然无效.该语言不允许您假装一种类型是另一种类型.你甚至不能治疗的情况下struct A { int i; };,如果它是一个struct B { int i; };.
该标准对对象的内存布局几乎没有提供保证。
对于类/结构:
9.2./15: 分配具有相同访问控制的类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。具有不同访问控制的非静态数据成员的分配顺序未指定。实现 对齐要求可能会导致两个相邻成员不能立即分配;管理虚拟函数和虚拟基类的空间要求也可能如此。
对于数组,元素是连续的。没有提到对齐,因此它可能会也可能不会使用与 struct 相同的对齐规则:
8.3.4: 数组类型的对象包含连续分配的 N 个类型 T 子对象的非空集合。
在您的具体示例中,您唯一可以确定的是,如果使用reinterpret_cast,则a.x对应于:arr[0]
9.2.21:指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(...),反之亦然。[
>