简体   繁体   中英

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* . Is it possible?

I started using OpenBlas which has double* parameter for complex values. 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 :

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.

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++. 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. 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. Using it from C++ is, of course, possible, but will not obtain the full typesafety etc of a C++ library. C libraries often accept void* and interpret it according to convention and/or other function parameters. This will not allow the compiler to check whether you're passing sensible values, in contrast to a C++ library.

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.

In your case here, a simple C-style cast or, equivalently, a reinterpret_cast<> will do.

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. 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).

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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