简体   繁体   English

将结构指针转换为双指针

[英]Cast struct pointer to double pointer

I am having the following structure: 我具有以下结构:

typedef struct 
{ 
    double r, i; 
} doublecomplex;

I would like to cast doublecomplex* to double* . 我想将doublecomplex*double* Is it possible? 可能吗?

I started using OpenBlas which has double* parameter for complex values. 我开始使用OpenBlas,它具有用于复杂值的double*参数。 I would also like to know if it is possible to do casting the other way around since some functions return openblas_complex_double which is : 我还想知道是否有可能进行其他方式的转换,因为某些函数返回openblas_complex_double ,即:

typedef struct { double real, imag; } openblas_complex_double;

Both types are layout compatible types in standard layout . 两种类型都是标准布局中的布局兼容类型。 Therefore, the C++ standard guarantees that a pointer to either struct may be safely reinterpret_cast ed to a pointer to its first data member. 因此,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;
}

Note however that while this is allowed, it is still rather poor style and you'll have to take a lot of care not to outsmart yourself. 但是请注意,尽管允许这样做,但样式仍然很差,您必须格外小心,以免表现出色。 If there is a way you can avoid doing that, you should. 如果有一种方法可以避免这样做,则应该这样做。

Also, please don't typedef your struct s in C++. 另外,请不要在C ++中对您的struct进行typedef It is completely unnecessary. 完全没有必要。

Yes. 是。 For plain old data types (POD) it is guaranteed that pointer to an instance of POD when suitably converted points to it's first data type. 对于普通的旧数据类型(POD),可以确保在适当转换后指向POD实例的指针指向其第一个数据类型。 Therefore you can do: 因此,您可以执行以下操作:

#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;
}

OpenBlas is a C library with a C API and C linkage. OpenBlas是具有C API和C链接的C库。 Using it from C++ is, of course, possible, but will not obtain the full typesafety etc of a C++ library. 当然可以从C ++使用它,但不能获得C ++库的完整类型安全性。 C libraries often accept void* and interpret it according to convention and/or other function parameters. C库通常接受void*并根据约定和/或其他功能参数对其进行解释。 This will not allow the compiler to check whether you're passing sensible values, in contrast to a C++ library. 与C ++库相比,这将使编译器无法检查您是否传递了有意义的值。

If your code is otherwise fully C++, you may consider using a C++ linear algebra package, or write your own type safe C++ interface (pure inline) to OpenBlas. 如果您的代码完全是C ++,则可以考虑使用C ++线性代数包,或将自己的类型安全的C ++接口(纯内联)编写到OpenBlas。

In your case here, a simple C-style cast or, equivalently, a reinterpret_cast<> will do. 就您的情况而言,将执行简单的C样式强制转换或等效的reinterpret_cast<>

As @5gon12eder points out, the address of the first member of a plain (C-style) struct is the same as that of the struct instance itself. 正如@ 5gon12eder所指出的,普通(C样式) struct的第一个成员的地址与该struct实例本身的地址相同。 BUT, there are some gotchas you need to be aware of. 但是,您需要注意一些陷阱。

First, that property doesn't hold for any other member of the struct, so you can't just cast a pointer to doublecomplex to a pointer to an array of double and use it to access any element beyond the first (you might be able to, but the language spec doesn't give you that guarantee). 首先,该属性并不适用于该结构的任何其他成员,所以你不能只投的指针doublecomplex的指针数组double ,并用它来访问任何元素超过第一(你也许能,但语言规范并不能为您提供保证)。

Second, it'll always be safer to access a member without any cast if you can 其次,如果可以的话,在没有任何强制转换的情况下访问成员总是比较安全的

const doublecomplex * dc;
const double * rp = & dc->r;
const double * ip = & dc->i;

is preferable to 优于

const doublecomplex * dc;
const double * rp = reinterpret_cast<const double *>(dc);
const double * ip = ???;

Now, if a function is receiving a double * as a parameter and you know it's element r of a doublecomplex , you can safely convert it to a doublecomplex * , but doing so is often asking for trouble because it requires that anyone calling the function follows that rule. 现在,如果一个函数接收double *作为参数,你知道它的元素r一的doublecomplex ,你可以放心地将其转换为doublecomplex * ,但这样做往往是自找麻烦,因为它需要有人调用该函数如下那条规则。

Ideally, your declarations should specify types with enough detail to avoid casts altogether, but as long as you're aware of the constraints imposed by the language (and the corresponding freedom afforded compiler implementers) there's a somewhat clear boundary between what is and isn't safe. 理想情况下,您的声明应指定足够详细的类型,以免完全进行强制类型转换,但只要您知道该语言所施加的约束(以及编译器实现者提供的相应自由度),在存在和存在之间就存在一个清晰的界限。安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM