2008-09-11 72 views
3

這是從this answer to a previous question of mine來的。 是否保證編譯器將array[4][4]array[16]相同?鑄造多維和單維陣列

例如,以下任一調用api_func()是否安全?

void api_func(const double matrix[4][4]); 

// ... 

{ 
    typedef double Matrix[4][4]; 

    double* array1 = new double[16]; 
    double array2[16]; 

    // ... 

    api_func(reinterpret_cast<Matrix&>(array1)); 
    api_func(reinterpret_cast<Matrix&>(array2)); 
} 

回答

3

從C++標準,指的是操作者sizeof

當應用於陣列,其結果是在陣列中的字節的總數。這意味着元素的大小爲n元素的大小爲n倍。

因此,我認爲double[4][4]double[16]必須具有相同的底層表示。

也就是說,給出

sizeof(double[4]) = 4*sizeof(double) 

sizeof(double[4][4]) = 4*sizeof(double[4]) 

那麼我們有

sizeof(double[4][4]) = 4*4*sizeof(double) = 16*sizeof(double) = sizeof(double[16]) 

我認爲一個符合標準的編譯器必須實現這些相同的,而且我認爲這不是編譯器意外破壞的東西。實現多維數組的標準方式按預期工作。打破標準將需要額外的工作,因爲可能沒有任何好處。

C++標準還規定,數組由連續分配的元素組成,這消除了使用指針和填充做任何奇怪事情的可能性。

0

我會被添加的東西像矩陣[5] [5],使對準每一行字擔心填充,但可能是簡單的我自己的迷信。

2

我不認爲有一個多維陣列引入的填充有問題。

數組中的每個元素必須滿足體系結構施加的填充要求。數組[N] [M]總是與[M * N]中的一個具有相同的內存表示形式。

1

每個數組元素都應該由編譯器按順序放在內存中。這兩個聲明雖然不同的類型是相同的底層內存結構。

0

更大的問題是:你真的需要執行這樣的演員嗎?

雖然你可能能夠擺脫它,它仍然是更具可讀性和可維護性,以避免完全。例如,您可以一直使用double [m * n]作爲實際類型,然後使用包裝此類型的類,並且可能重載[]運算符以便於使用。在這種情況下,您可能還需要一箇中間類來封裝單個行 - 這樣像my_matrix [3] [5]這樣的代碼仍可按預期工作。

1

@Konrad魯道夫:

我摻和進去自己那兩個(行大/列爲主),但我知道這一點:這是很明確的。例如,int x [3] [5]是一個大小爲3的數組,其元素是大小爲5的int數組。(§6.5.2.1)從標準關於數組中添加所有規則,尋址,等等,你會得到第二個下標引用連續整數,第一個下標將引用連續的5-int對象。 (所以3是更大的數字;你有5個整數在x [1] [0]和x [2] [0]。)