我有以下结构:
typedef struct
{
double r, i;
} doublecomplex;
我想将doublecomplex*
投射到double*
。有可能吗?
我开始使用OpenBlas,它具有复杂值的double*
参数。我还想知道是否有可能以相反的方式进行转换,因为某些函数返回openblas_complex_double
,这是:
typedef struct { double real, imag; } openblas_complex_double;
答案 0 :(得分:1)
这两种类型都是standard layout中与布局兼容的类型。因此,C ++标准保证指向struct
的指针可以安全地reinterpret_cast
指向其第一个数据成员的指针。
double
get_real_part(const doublecomplex *const ptr)
{
static_assert(std::is_standard_layout<doublecomplex>::value,
"cast of non-standard layout type is not safe");
const double *const realptr = reinterpret_cast<const double *>(ptr);
return *realptr;
}
但请注意,虽然这是允许的,但它仍然是相当差的风格,你必须要非常小心,不要超越自己。如果有办法,你可以避免这样做,你应该。
另外,请不要在{+ 1}} {C}中使用typedef
。这是完全没必要的。
答案 1 :(得分:0)
是。对于普通旧数据类型(POD),保证在适当转换时指向POD实例的指针指向它的第一个数据类型。因此你可以这样做:
#include <iostream>
struct doublecomplex
{
double r, i;
};
int main() {
doublecomplex d{1,2};
double *dp = reinterpret_cast<double*>(&d);
std::cout << *dp << 1[dp]; // ==dp[1]==convoluted way to say dp+1
return 0;
}
答案 2 :(得分:0)
OpenBlas是一个带有C API和C链接的C库。当然,在C ++中使用它是可能的,但是不会获得C ++库的完整类型安全等。
C库通常接受void*
并根据约定和/或其他函数参数对其进行解释。与C ++库相比,这不允许编译器检查您是否通过了合理的值。
如果您的代码完全是C ++,您可以考虑使用C ++线性代数包,或者将自己的类型安全C ++接口(纯内联)编写到OpenBlas。
在这种情况下,一个简单的C风格的演员表,或者等同于reinterpret_cast<>
。
答案 3 :(得分:0)
正如@ 5gon12eder所指出的那样,普通(C风格)struct
的第一个成员的地址与struct
实例本身的地址相同。但是,你需要注意一些问题。
首先,该属性不适用于 结构的任何其他 成员,因此您不能只将doublecomplex
的指针强制转换为指向double
数组的指针,并使用它来访问第一个以外的任何元素(可能能够,但语言规范不能为您提供保证)。
其次,如果可以
,访问没有任何演员的会员总是更安全const doublecomplex * dc;
const double * rp = & dc->r;
const double * ip = & dc->i;
优于
const doublecomplex * dc;
const double * rp = reinterpret_cast<const double *>(dc);
const double * ip = ???;
现在,如果某个功能正在接收double *
作为参数,而您 知道 ,则r
的元素doublecomplex
,你可以安全地将它转换为doublecomplex *
,但这样做往往会引起麻烦,因为它要求任何调用该函数的人遵循该规则。
理想情况下,您的声明应该指定具有足够详细信息的类型以完全避免强制转换,但只要您了解语言所施加的约束(以及编译器实现者提供的相应自由),就会有一些明确的界限。并且不安全。