2015-01-17 4 views
0

Я имею следующую структуру:Cast указатель структура двойной указатель

typedef struct 
{ 
    double r, i; 
} doublecomplex; 

Я хотел бы, чтобы бросить к double*. Является ли это возможным?

Я начал использовать OpenBlas с параметром double* для сложных значений. Я также хотел бы знать, если это возможно сделать отливку наоборот, так как некоторые функции возвращают openblas_complex_double что:

typedef struct { double real, imag; } openblas_complex_double; 
+1

Действительно ли это C++? Является OpenBlas? Это очень похоже на C-код. – Walter

+1

Хотя литье 'doublecomplex *' to 'double *' является законным, зачем вам это нужно? Это проще и безопаснее писать '& someDoubleComplex.r', чем' reinterpret_cast (& someDoubleComplex) '. – jamesdlin

ответ

1

Оба типа макета совместимых типов в standard layout. Поэтому стандарт C++ гарантирует, что указатель на struct может быть безопасным reinterpret_cast ed указателю на его первый элемент данных.

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

Однако обратите внимание, что в то время как это разрешено, это все еще довольно плохой стиль, и вы должны будете принять много заботы не перехитрить себя. Если есть способ, которым вы можете избежать этого, вам нужно.

Также, пожалуйста, не typedefstruct s в C++. Это совершенно не нужно.

+0

OpenBlas - это библиотека C, поэтому стандарт C++ не имеет прямого отношения. – Walter

+0

Таким образом, возвращаемое значение будет 'r'? Как он получит «я»? –

+0

@Walter Вопрос был отмечен C++, вот что я имею в виду. Во всяком случае, стандартная компоновка POD тип также гарантированно совместим с C, поэтому все равно должно быть хорошо. – 5gon12eder

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

OpenBlas - это библиотека C с C API и C-связью. Разумеется, использование его из C++ возможно, но не получит полную информацию о типах и т. Д. Библиотеки C++. Библиотеки C часто принимают void* и интерпретируют его в соответствии с соглашением и/или другими параметрами функции. Это не позволит компилятору проверить, передаете ли вы разумные значения, в отличие от библиотеки C++.

Если ваш код в остальном полностью C++, вы можете рассмотреть возможность использования пакета линейной алгебры C++ или написать собственный безопасный C++-интерфейс (чистый встроенный) на OpenBlas.

В вашем случае здесь будет выполнен простой C-образный литой или, что то же самое, reinterpret_cast<>.

0

Как указывает @ 5gon12eder, адрес первого элемента равнины (C-style) 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 * в виде параметр и вы know его элемент rdoublecomplex, вы можете смело преобразовать его в doublecomplex *, но при этом часто возникает проблема, потому что это требует, чтобы кто-либо, вызывающий функцию, следовал этому правилу.

В идеале ваши объявления должны указывать типы с достаточной детализацией, чтобы избежать приведения в целом, но до тех пор, пока вы знаете о ограничениях, налагаемых языком (и соответствующей свободе, предоставляемой разработчиками компилятора), есть несколько четкая граница между тем, что является и не является безопасным.

Смежные вопросы