将struct指针转换为双指针

时间:2015-01-17 18:48:32

标签: c++ pointers casting

我有以下结构:

typedef struct 
{ 
    double r, i; 
} doublecomplex;

我想将doublecomplex*投射到double*。有可能吗?

我开始使用OpenBlas,它具有复杂值的double*参数。我还想知道是否有可能以相反的方式进行转换,因为某些函数返回openblas_complex_double,这是:

typedef struct { double real, imag; } openblas_complex_double;

4 个答案:

答案 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 *,但这样做往往会引起麻烦,因为它要求任何调用该函数的人遵循该规则。

理想情况下,您的声明应该指定具有足够详细信息的类型以完全避免强制转换,但只要您了解语言所施加的约束(以及编译器实现者提供的相应自由),就会有一些明确的界限。并且不安全。