C++ 将Vec*转换为双精度*
我试图理解一个框架,并慢慢地调试它。在我的例子中,我有一个向量数组,用指针存储:C++ 将Vec*转换为双精度*,c++,arrays,casting,C++,Arrays,Casting,我试图理解一个框架,并慢慢地调试它。在我的例子中,我有一个向量数组,用指针存储: Vec *cx =....; My Vec是一个定义如下的结构: struct Vec { double x, y, z; // position, also color (r,g,b) Vec(double x_ = 0, double y_ = 0, double z_ = 0){ x = x_; y = y_; z = z_; } Vec opera
Vec *cx =....;
My Vec是一个定义如下的结构:
struct Vec {
double x, y, z; // position, also color (r,g,b)
Vec(double x_ = 0, double y_ = 0, double z_ = 0){ x = x_; y = y_; z = z_; }
Vec operator+(const Vec &b) const { return Vec(x + b.x, y + b.y, z + b.z); }
Vec operator-(const Vec &b) const { return Vec(x - b.x, y - b.y, z - b.z); }
Vec operator-() const { return Vec(-x, -y, -z); }
Vec operator*(double b) const { return Vec(x*b, y*b, z*b); }
Vec mult(const Vec &b) const { return Vec(x*b.x, y*b.y, z*b.z); }
Vec& norm(){ return *this = *this * (1 / sqrtf(x*x + y*y + z*z)); }
double dot(const Vec &b) const { return x*b.x + y*b.y + z*b.z; } // cross:
Vec operator%(Vec&b){ return Vec(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x); }
double max() const { return x>y && x>z ? x : y > z ? y : z; }
};
我想知道如果我把一个向量数组转换成一个双倍数组,会发生什么。实际上:
double * cast = (double*)cx;
它给了我什么
为了理解,我试着这样做:
Vec boh = Vec(1.0, 1.0, 1.0);
Vec boh2 = Vec(2.0, 2.0, 2.0);
Vec * try = new Vec[2];
try[0] = boh;
try[1] = boh2;
double* try2= (double*)try;
我意识到try指向第一个Vec,即boh1,因此如果我进行调试,我会看到x、y、z值设置为1。同样,try2应该指向与boh1相关的“某物”,但调试显示try2的值为1.000000。那么,到底发生了什么
<>编辑:“尝试”不能用作C++中变量的名称。 它仍然会给你一个指向
Vec
的指针,这根本不是一个双精度
。强制转换所做的是告诉编译器完全忽略try
的实际类型,实际上假装try
不是
使用
try2
将导致未定义的行为。它仍然会给您一个指向Vec
的指针,这根本不是一个双重
。强制转换所做的是告诉编译器完全忽略try
的实际类型,实际上假装try
不是
使用
try2
将导致未定义的行为。程序的行为未定义
本质上,
sizeof(double)
与sizeof(Vec)
不同,因此所有指针算法和数组索引都将在C样式转换后崩溃。程序的行为未定义
本质上,sizeof(double)
与sizeof(Vec)
不同,因此所有指针算法和数组索引都会在C样式转换后崩溃。实际发生的是,由于结构的数据成员是3个double,您的同事正在指望C行为,他们将内存视为double
而不是Vec
。在C语言中,它的作用类似于一个“并集”,即内存中的结构布局只有3个双倍。在您的情况下(使用C++),它就像一个工会一样(请参见编辑)。因此,您正在从boh
(您称之为boh1
)访问1.0。其他人说,这种行为是不明确的。我相信“依赖于实现”可能更准确,但我会遵从它们(除非我能找到参考资料)
无论如何,如果可以的话,您的代码示例已经成熟,可以进行重构了。如果你的同事依赖这种行为,他们应该清楚地识别出来,这样其他人就不会跟着改变结构
编辑:好的,我发现了一个参考,表明这不是未定义的行为(除非我误解了该参考)。结构是一个POD结构,每节9(SS7,10)的C++ + Po.Pod(普通旧数据)布局在9.2(SS13)中描述。
9 ss10POD结构110是一个非联合类,它既是普通类又是标准布局类,并且没有非POD结构、非POD联合(或此类类型的数组)类型的非静态数据成员。类似地,POD联合是一个联合,它既是普通类又是标准布局类,并且不具有非POD结构、非POD联合(或此类类型的数组)类型的非静态数据成员。POD类是一个POD结构或POD联合的类 9 ss7
S类是标准布局类,如果:
-(7.1)没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
-(7.2)没有虚拟函数(10.3)和虚拟基类(10.1),
-(7.3)对所有非静态数据成员具有相同的访问控制(第11条),
-(7.4)没有非标准布局基类,
-(7.5)最多有一个给定类型的基类子对象,
-(7.6)类中的所有非静态数据成员和位字段及其基类首先在同一类中声明,以及
-(7.7)没有类型(定义如下)集合M(S)中的元素作为基类。109 9.2 ss13
具有相同访问控制(第11条)的(非联合)类的非静态数据成员被分配,以便后面的成员在类对象中具有更高的地址。具有不同访问控制的非静态数据成员的分配顺序未规定(第11条)。实施一致性要求可能会导致两个相邻的成员不能紧随其后进行分配;管理虚拟函数(10.3)和虚拟基类(10.1)的空间需求也是如此 因此,我怀疑你的同事是依靠吊舱布局来获得“联盟”式的行为。我仍然认为这是一种非常糟糕的做法。如果无法避免,则应添加编译时检查或记录结构以确定此要求。实际发生的情况是,由于结构的数据成员是3个双倍,您的同事正在指望C行为,他们将内存视为
double
而不是Vec
。在C语言中,它的作用类似于一个“并集”,即内存中的结构布局只有3个双倍。在您的情况下(使用C++),它就像一个工会一样(请参见编辑)。因此,您正在从boh
(您称之为boh1
)访问1.0。其他人说,这种行为是不明确的。我相信“依赖于实现”可能更准确,但我会遵从它们(除非我能找到参考资料)
无论如何,如果可以的话,您的代码示例已经成熟,可以进行重构了。如果你的同事依赖这种行为,他们应该清楚地识别出来,这样其他人就不会跟着改变结构