2012-06-13 51 views
4

我想寫一個C函數,它將動態二維數組作爲輸入,但不會更改數組。C函數,需要const 2d數組

我想要是const正確的,不僅使我的代碼更加清晰,而且因爲我的函數將從C++代碼中調用,並且C++對於這些事情非常自信。

我該如何聲明一個函數將'const'指針指向一個指針,即如何指示該函數不會改變2d數組的內容?

以下是一個特定的超級簡單示例。我使用雙打的2D陣列,即雙**,以表示尺寸爲n×n的℃的正方形矩陣,並且我想要寫,計算這些矩陣中的一個的軌跡的函數:

#include <stdlib.h> 
#include <stdio.h> 

double **sqr_matrix_new(int n) 
{ 
    double **a = calloc(n, sizeof(double*)); 
    int i; 
    for (i=0; i < n; ++i) a[i] = calloc(n, sizeof(double)); 
    return a; 
} 

void sqr_matrix_free(double **a, int n) 
{ 
    int i; 
    for (i=0; i < n; ++i) free(a[i]); 
    free(a); 
} 

double sqr_matrix_trace(double **a, int n) 
{ 
    double trace; 
    int i; 
    for (i=0, trace=0.0; i < n; ++i) trace += a[i][i]; 
    return trace; 
} 

double sqr_matrix_trace_const(const double * const *a, int n) 
{ 
    double trace; 
    int i; 
    for (i=0, trace=0.0; i < n; ++i) trace += a[i][i]; 
    return trace; 
} 

int main(int argc, char *argv[]) 
{ 
    int n = 10; 
    double **a = sqr_matrix_new(n); 
    int i, j, k; 
    for (i=0, k=0; i < n; ++i){ 
    for (j=0; j < n; ++j) a[i][j] = k++; 
    } 
    printf("trace is %g\n", sqr_matrix_trace(a, n)); 
    printf("trace is %g\n", sqr_matrix_trace_const(a, n)); 
    printf("trace is %g\n", sqr_matrix_trace_const((const double * const *)a, n)); 
    sqr_matrix_free(a, n); 
} 

在上面,跟蹤函數sqr_matrix_trace()和sqr_matrix_trace_const()的兩個版本乾淨地編譯(後者是我更喜歡的版本,因爲它清楚地表明將不會改變它給出的矩陣),但是調用

sqr_matrix_trace_const(a, n) 

產生以下警告:

sqr_matrix.c: In function 'main': 
sqr_matrix.c:44: warning: passing argument 1 of 'sqr_matrix_trace_const' from incompatible pointer type 
sqr_matrix.c:27: note: expected 'const double * const*' but argument is of type 'double **' 

演員克服了這個:

sqr_matrix_trace_const((const double * const *)a, n) 

但感覺不對使用強制使用克服編譯器的不便。

另外,我可以禁止編譯器警告,但這是一個警察。

所以,我希望我的代碼能夠乾淨地編譯,並且我希望傳遞給函數的動態二維數組的常量,而不是通過強制轉換。這似乎是一個合法的目標。這可能嗎?如果不是,那麼這樣做的標準/被接受​​的做法是什麼?

+0

Duplicate:http://stackoverflow.com/questions/4573349/c-function-const-multidimensional-array-argument-strange-warning – math

回答

3

C const促銷規則不允許從T **const T const *的促銷。根據6.5.16.1 1(它適用於函數調用以及6.5.2.2 2中的賦值),指針的轉換隻能爲指向類型添加限定符。

這是爲了防止類似的代碼(例如,從6.5.16.1 6):

const char **cpp; 
char *p; 
const char c = 'A'; 
cpp = &p; // constraint violation 
*cpp = &c; // valid 
*p = 0; // valid 

這是正確的觀察,因爲那時*cpp = &c防止const *const *cpp = &p是安全的,但是這是一個足夠模糊的情況下,它不在標準中涵蓋。

結論:你可以並且應該自己投給const double *const *

注意,這將是更有效地使用double *類型的單個陣列長度n * n並執行任何必要的數組索引自己:d[i][j]變得d[i * n + j]

+0

感謝指針(雙關語意)到C常見問題。 – user1453344

+0

我認爲該評論意在爲米蘭的答案http://stackoverflow.com/a/11014916/567292? – ecatmur

0

如果你的矩陣數據真的是二維和矩形(沒有「衣衫襤褸的右邊緣」),我不明白你爲什麼不把它表示爲第一個元素的單個double *,連同整數給出寬度和高度。這將允許您減少初始化矩陣所需的分配數量,但也可以將其表示爲普通舊const double *