我想编写一个将动态二维数组作为输入但不改变数组的 C 函数。
我试图使 const 正确,不仅是为了使我的代码更清晰,而且因为我的函数将从 C++ 代码中调用,而 C++ 对这些事情非常挑剔。
如何声明一个函数以将“const”指针指向一个指针,即如何指示该函数不会改变二维数组的内容?
下面是一个具体的、超级简单的例子。我正在使用一个二维的双精度数组,即 double** 来表示一个大小为 nxn 的 C 方阵,我想编写一个函数来计算这些矩阵之一的轨迹:
#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)
但是使用强制转换来克服编译器的不便感觉是错误的。
或者,我可以禁止编译器警告,但这是一种逃避。
因此,我希望我的代码能够干净地编译,并且我想传达给函数的动态二维数组的 const 特性,而无需借助强制转换。这似乎是一个合法的目标。这可能吗?如果没有,这样做的标准/公认做法是什么?