簡體   English   中英

將結構指針轉換為雙指針

[英]Cast struct pointer to double pointer

我具有以下結構:

typedef struct 
{ 
    double r, i; 
} doublecomplex;

我想將doublecomplex*double* 可能嗎?

我開始使用OpenBlas,它具有用於復雜值的double*參數。 我還想知道是否有可能進行其他方式的轉換,因為某些函數返回openblas_complex_double ,即:

typedef struct { double real, imag; } openblas_complex_double;

兩種類型都是標准布局中的布局兼容類型。 因此,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;
}

但是請注意,盡管允許這樣做,但樣式仍然很差,您必須格外小心,以免表現出色。 如果有一種方法可以避免這樣做,則應該這樣做。

另外,請不要在C ++中對您的struct進行typedef 完全沒有必要。

是。 對於普通的舊數據類型(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;
}

OpenBlas是具有C API和C鏈接的C庫。 當然可以從C ++使用它,但不能獲得C ++庫的完整類型安全性。 C庫通常接受void*並根據約定和/或其他功能參數對其進行解釋。 與C ++庫相比,這將使編譯器無法檢查您是否傳遞了有意義的值。

如果您的代碼完全是C ++,則可以考慮使用C ++線性代數包,或將自己的類型安全的C ++接口(純內聯)編寫到OpenBlas。

就您的情況而言,將執行簡單的C樣式強制轉換或等效的reinterpret_cast<>

正如@ 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 * ,但這樣做往往是自找麻煩,因為它需要有人調用該函數如下那條規則。

理想情況下,您的聲明應指定足夠詳細的類型,以免完全進行強制類型轉換,但只要您知道該語言所施加的約束(以及編譯器實現者提供的相應自由度),在存在和存在之間就存在一個清晰的界限。安全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM