簡體   English   中英

ANSI C中內存中的二維數組

[英]2-Dimensional array in memory in ANSI C

我在這里和其他網站上看過很多人說如果宣布這樣的話:

double a[5][2];

它將在內存中分配,如:連續塊,如:

a[0][0] | a[0][1] | a[1][0] | a[1][1] | ....etc

但這總是一個規律嗎? 我想創建一個函數來乘以可變大小的矩陣,但在純CI中,如果不知道至少一個維度,就不能通過參數傳遞矩陣。 所以我做了這個:

void MatMult(double* m1, double* m2, double* res, int h, int w, int l)
{
  int i, j, k;
  for (i = 0; i < h; i++)
  {
    for (j = 0; j < w; j++)
    {
        double p_res = 0;
        for (k = 0; k < l; k++)
        {
            p_res += (*(m1+i*l+k))*(*(m2+k*w+j));
        }
        *(res+i*w+j)=p_res;
    }
  }
}

隨叫隨到:

 double m1[2][3], m2[3][1], m3[2][1];
 ...
 MatMult(&(m1[0][0]),&(m2[0][0]),&(m3[0][0]),2,1,3);

它奏效了。 但這會一直有效還是我應該注意的例外情況,如內存對齊或類似的東西?

要將2D數組傳遞給函數,您必須更改接口

void MatMult(size_t h, size_t w, size_t l. double m1[h][w], double m2[w][l], double res[h][l]);

或類似的:

  • 首先是尺寸
  • 然后用它們來聲明尺寸

此外,我在這里使用了size_t ,因為這是所有索引計算的正確類型。

這適用於所有實現C99的編譯器。 (基本上所有人都可以做到。)

是的,它總能奏效。 聲明像你做的ara保證是“連續的”,這意味着他們的物品將被緊緊包裝起來。 所以,如果你聲明double[55]你就會知道[50] -th元素總是會在[49]元素之后,沒有可感知的間隙。

我想,但我不完全確定,對於一些非常罕見的數據類型(如包括不平衡的位域等),“對齊”仍然可以啟動並抵消某些東西。 我不確定。 即使 (參見Jens評論)如果編譯器添加了一些對齊偏移,它將在單個數據元素內部或在元素之間的boudary中這樣做,並且在兩種情況下編譯器都會知道它。 因此,它應該在每個[], ->, .應用所有必需的更正[], ->, . 操作,只要它仍然具有所有必需的類型信息(double-number)。 如果刪除類型信息並開始通過“無類型”(或錯誤類型)指針訪問數組,例如:

double array[50];
char* p = (char*)array;
int size = sizeof(double);
for(i=0;i<50;++i)
    .. *(double*)(p+size) ..

那么編譯器當然沒有類型信息,也無法應用正確的對齊偏移。 但是如果你按照上面所做的那樣做,你可能已經知道了風險。

接下來的是,沒有二維數組這樣的東西。 既不是C語言,也不是C ++語言。

定義為double[5][2]的數組是double的數組(2)的數組(5)。 CMIIW,我可以交換它們。 無論如何,關鍵是'double'是一種數據類型,是更高級別1D陣列的元素。 然后, double[2]是數據類型和更高級別1D數組的元素,依此類推。

現在,請記住數組的“順序+連續”布局:

double            ->  DD
double[2]         -> [DD | DD]
double[5][2]      -> [ {DD:DD} | {DD:DD} | {DD:DD} | {DD:DD} | {DD:DD} ]

由於數組必須是連續的和連續的,所以double [2]必須將其元素布局如上 - 顯而易見。

但是,由於double [5] [2]是一個數組,它的數組是[5],並且由於它的元素是double [2] - 它必須以相同的方式布局它的元素。 首先是整個元素,然后是第二個整數元素,依此類推。

就像double [2]不能將其雙精度“拆分”成分散的1字節塊一樣,double [5] [2]不能拆分它的數組[2]。

通過使用double a[5][2] ,您將在堆棧中創建二維數組,它始終是一個連續的內存塊。 另一方面,如果您嘗試在堆上創建二維數組(即使用malloc),則無法保證您將獲得連續的內存塊,因此您可能無法以線性方式遍歷已分配的內存。

暫無
暫無

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

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