與C++

2009-08-16 12 views
2

2D陣列我有一個功能,需要一個指針的指針的作爲參數。與C++

func(double **arr, int i); 

,其中在主函數數組定義如下:

double arr[][] = //some initialization here; 

我怎麼能說從我的主要代碼此功能。我嘗試了以下,但它給出了一個錯誤

func (&arr); 

不起作用。任何幫助將非常感激。 謝謝

回答

10

A double **pdouble[][] a是不一樣的,所以你不能通過一個爲另一個。

特別地,二維數組變量是含有可以與[][]語法訪問雙打存儲器的(單!)塊。此要求,編譯器知道數組的維數,以使得它可以計算正確的偏移量,以每一個元素。它也可以透明地衰減到指向該內存塊的指針,但是這樣做會失去對如何以二維數組訪問該內存的理解:它實際上變成了一個指向double的指針。

+----+   +---------+---------+---------+ 
| (a---------->) | a[0][0] | a[0][1] | a[0][2] | ... 
+----+   +---------+---------+---------+ 
       | a[1][0] | a[1][2] | ... 
       +---------+---------+ 
        ... 

由函數預期的東西是一個指針,指向包含一個或多個指針,以含有存儲器雙打的附加塊的存儲塊。

+---+  +------+  +---------+---------+ 
| p-------->| p[0]------->| p[0][0] | p[0][3] | ... 
+---+  +------+  +---------+---------+ 
      | p[1]--\  
      +------+ \ +---------+---------+ 
      ...  --->| p[1][0] | p[1][4] | ... 
          +---------+---------+ 

雖然語法看起來很相似,但這兩個結構的語義完全不同。


更完整的討論,請參見my answerprevious questions(實際上地址C,但問題是相同的)。

+0

那麼如何將數組傳遞給我的func?我很困惑。我想在不改變聲明的情況下將其傳遞給func。 – zack 2009-08-16 22:28:16

16

arr的類型是double[X][Y] - 也就是說,一個Y數組的雙倍數組 - 其中XY依賴於您的初始值設定項。這是不是與指針類型相同。但是,根據C轉換規則,數組可以衰減爲指向其元素的指針。在你的情況下,由這種衰減產生的類型將是double(*)[Y] - 指向Y雙精度數組的指針。注意,這是一個指針陣列,而不是一個數組指針的,所以它不會進一步衰減任何。此時,由於函數預期爲double**,因此會出現類型不匹配的情況。

來處理這個正確的方法是治療所述陣列爲單維的,並沿着通寬度。所以:

void func(double* arr, int w) { 
    // arr[2][3] 
    arr[2*w + 3] = ...; 
} 


double x[6][8] = { ... }; 
func(&x[0][0], 8); 

在C++特別是,如果你總是有靜態分配知名(但不同)類型的數組,你可以使用模板和引用這樣的:

template <int W, int H> 
inline void func(const double (&arr)[W][H]) { 
    arr[2][3] = ...; 
} 

double x[6][8] = { ... }; 
func(x); // W and H are deduced automatically 

但是,當你已經是一個指針(例如,當陣列是new -allocated,其大小是在運行時計算),這將無法正常工作。對於最常見的情況,您應該使用C++容器。使用標準庫只,一個通常使用的載體的載體:

#include <vector> 

void func(std::vector<std::vector<double> > arr) { 
    arr[2][3] = ...; 
} 

std::vector<std::vector<double> > x(6, std::vector<double>(8)); 
x[0][0] = ...; 
... 
func(x); 

如果可以使用Boost,它有一個非常漂亮的MultiArray庫在它:

void func(boost::multi_array<double, 2> arr) { // 2 means "2-dimensional" 
    arr[2][3] = ...; 
} 

boost::multi_array<double, 2> x(boost::extents[6][8]); 
x[0][0] = ...; 
... 
func(x); 

[編輯]你說你不能改變你的函數的定義。如果是這樣,那麼它確實是一個將它的參數當作一個指針數組來處理的函數,所以你應該相應地分配你的數據結構。例如:

double x1[8] = { 1, 2, ... }; 
double x2[8] = { 3, 4, ... }; 
... 
double* x[6] = { x1, x2, ... }; 

func(x); 
+0

不錯,全面。但是如果你不能改變fn呢?只需將它包裝起來,這樣頂層數組的數組就是堆棧本地的(堆棧分配或異常安全的堆)。也就是說,2d數組本身包含連續的1d數組,您可以指向它們。 – 2009-08-16 22:44:50

+0

或者,你可以使用漂亮的初始化器語法來創建一堆單獨的1d數組並指向它們。數組初始值設定語法僅在頂級範圍內可用,對嗎? – 2009-08-16 22:46:19

+0

好點,我會編輯。數組初始值設定項在任何範圍內都可用(包括本地/自動),但不在'new'中。 – 2009-08-16 23:56:53

-1
func(double *arr[100]) 

你需要告訴編譯器尺寸的大小,以便它可以創建正確的地址

arr[y][x] 

變成

arr[100*x+y] 

如果定義你的函數作爲func(double ** a),那麼你正在說一個指向dmckee指出的指針數組的指針