2017-04-05 33 views
1

工作指針,我有以下兩個功能:C編程 - 函數中使用與多維數組

double** transpose(double **a, int r, int c){ 
    static double trans[100][100]; 
    int i,j; 
    for(i = 0; i < r; i++) 
     for(j = 0; j < c; j++) 
      trans[j][i] = a[i][j]; 
    return trans; 
} 

double(*matrixMultiply(double a[10][10], double b[10][10], 
    int rowA, int colB, int colARowB))[10]{ 
    static double c[10][10]; 
    int i, j, k; 
    for(i = 0; i < rowA; i++) 
     for(j = 0; j < colB; j++){ 
      c[i][j] = 0; 
      for(k = 0; k < colARowB; k++) 
       c[i][j] += a[i][k]*b[k][j]; 
     } 
    return (double*) c; 
} 

雖然我明白的算法,能有人給我解釋一下什麼這兩個函數返回(類型,指針。 ..)?第二個似乎返回數組,但我認爲在C函數不能返回數組...

掌握這些指針真的很困惑......

而且爲什麼是陣列(transc)聲明爲靜態?據我所知,當你聲明一個變量或函數與靜態它不能被導入用於另一個文件,但這是在這裏肯定不是這種情況...

+2

'double **'是**不是**二維數組,並且不能指向一個。指針不是數組。不,你不能將數組傳遞給函數。但是你可以傳遞指向數組的指針。 – Olaf

回答

3

這兩個函數都試圖返回指針數組。兩者都是這樣做是錯誤的並且無法在我的系統上編譯。

除了當它是sizeof或一元&運營商的操作數,或是使用在聲明初始化字符數組文本字符串,類型「的T N元件陣列」的表達將被轉換(「衰減」)轉換爲類型爲「指向T的指針」的表達式,並且表達式的值將是該數組的第一個元素的地址。

transpose函數中,我們返回表達式transtrans具有類型「012-的100-元素陣列」,其中T是「100-元素陣列double」。它不是sizeof或一元&操作符的操作數,所以它被轉換(「衰減」)爲「指向T」類型的表達式,在這種情況下,它是「指向100個元素的數組double」(double (*)[100]) ,不是「指向double的指針的指針」,(double **)。

編譯器應該抱怨那個函數。礦確實,像這樣:

gcc -c -std=c99 -pedantic-errors -Wall transpose.c 
transpose.c: In function âtransposeâ: 
transpose.c:7: error: return from incompatible pointer type 

matrixMultiply功能,c具有類型「的double 10元件陣列的10個元素的陣列」,其中「衰減」到「指針至10個元素的數組的double」 (double (*)[10])。第二個函數具有正確的返回類型 - double (*)[10] - 但他們搞砸了由return語句鑄造cdouble *,我們得到了相同的錯誤面前:

gcc -c -std=c99 -pedantic-errors -Wall matrixMultiply.c 
matrixMultiply.c: In function âmatrixMultiplyâ: 
matrixMultiply.c:11: error: return from incompatible pointer type 

他們剛纔寫的

return c; 

和一切都會好起來的。

來讀取第二函數定義的方法如下:

 matrixMultiply       -- matrixMultiply 
     matrixMultiply(     )  -- is a function taking 
     matrixMultiply(/* some params */)  -- some parameters (omitted for brevity) 
     *matrixMultiply(/* some params */)  -- returning a pointer 
     (*matrixMultiply(/* some params */))[10] -- to a 10-element array 
double(*matrixMultiply(/* some params */))[10] -- of double 

注意,唯一的原因要麼功能有工作(一旦類型問題理順了)的一個希望是,無論transc被宣佈爲static,這意味着它們的生命週期遍及整個程序,而不僅僅是它們各自功能的生命週期。沒有那個static關鍵字,他們在它們的封閉函數返回後不再存在,那些指針將變爲無效

這不一定是好的做法 - 這些功能不再是可重入的,也不是線程安全的。最好將目標數組作爲參數傳遞給函數,但請注意,指向10元素數組的指針與指向11元素數組的指針是不同的,不兼容的類型 - 如果必須處理數組不同數量的列,這可能會變得棘手。沃拉斯可以與幫助:

void transpose(int r, int c, double arr[r][c], double trans[c][r]) 
{ 
    ... 
} 

假設你有VLAS可用(你應該對C99和C2011系統,雖然他們已經在C2011已經取得可選)。如果你不......這會變得更加困難。

+2

返回一個指向靜態對象的指針的另一個問題,就像這裏所做的那樣,可能會出現意外的混疊。在OP的情況下,這是一個特殊的風險 - 如果其中一個函數的返回值作爲後續調用中的參數傳遞迴該函數,那麼實際行爲不可能是預期的。或者,如果對任一函數執行單獨和獨立的調用,則可能會驚奇的是之前的調用返回的指針指向不同的數據。 –

+0

非常感謝您的回答,以及您花時間寫下這些內容的時間。現在很清楚。我對功能上的錯誤感到抱歉,但在我的辯護中,他們不是我的。我從昨天的編程課程複製粘貼它們。似乎老師沒有注意......哦,好吧。 – ROBlackSnail

+0

@ROBlackSnail:對於那些自己被教導得很差的人來說,C幾乎一律教好,而數組/指針語義學是大量錯誤信息和不良習慣轉移的地方之一。這不是一個很好的*學習*資源,但將C語言標準的[當前在線草案](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)如果沒有別的,它會告訴你如何東西*假設*工作。 –