接受const 2d数组的C函数 [英] C function that takes const 2d array
问题描述
我想编写一个将动态2D数组作为输入但不改变数组的C函数。
I want to write a C function that takes a dynamic 2D array as an input, but doesn't alter the array.
我试图成为const正确,不仅使我的代码更清晰,而且因为将要从C ++代码中调用我的函数,并且C ++对这些事情相当拘谨。
I'm trying to be const correct, not only to make my code clearer, but because my functions are going to be called from within C++ code, and C++ is pretty persnickety about these things.
我声明一个函数以'const'指针指向一个指针,即如何指示该函数不会更改2d数组的内容?
How do I declare a function to take 'const' pointer to a pointer, i.e. how do I indicate that the function will not alter the contents of the 2d array?
接下来是什么一个具体的,超简单的示例。我使用2D数组(即double **)来表示大小为nxn的C中的方阵,我想编写一个函数来计算这些矩阵之一的踪迹:
What follows is a specific, super-simple example. I'm using a 2D array of doubles, i.e. double**, to represent a square matrix in C of size n x n, and I want to write a function that computes the trace of one of these matrices:
#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 ()干净地进行编译(我更喜欢后者,因为它清楚地表明了给出的矩阵不会改变),但是调用
In the above, both versions of the trace function, sqr_matrix_trace() and sqr_matrix_trace_const() compile cleanly (the latter is the one I prefer because it clearly demonstrates that there will be no alteration of the matrix it's given), but the call
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)
,但是使用强制转换来克服编译器的不便感觉是错误的。
but it feels wrong to use a cast to use to overcome compiler inconveniences.
或者,我可以禁止编译器warni ng,但这只是一个解决方案。
Alternatively, I could suppress the compiler warning, but that's a cop-out.
因此,我希望代码能够干净地编译,并且希望传达给对象的动态2D数组的恒定性。功能而无需强制转换。这似乎是一个合理的目标。这可能吗?如果没有,执行此操作的标准/可接受的惯例是什么?
So, I want my code to compile cleanly and I want to convey the const-ness of a dynamic 2D array given to a function without resorting to a cast. It seems like a legitimate aim. Is this possible? If not, what's the standard/accepted practice for doing this?
推荐答案
C const
升级规则不允许将 T **
升级为 const T const *
。根据6.5.16.1 1(适用于函数调用以及6.5.2.2 2的赋值),指针的转换只能将限定符添加到指向的类型。
The C const
promotion rules don't allow promotion from T **
to const T const *
. Per 6.5.16.1 1 (which applies to function calls as well as assignments per 6.5.2.2 2), conversion of pointers can only add qualifiers to the pointed-to type.
这是为了防止这样的代码(例如6.5.16.1 6中的示例):
This is to prevent code like (example from 6.5.16.1 6):
const char **cpp;
char *p;
const char c = 'A';
cpp = &p; // constraint violation
*cpp = &c; // valid
*p = 0; // valid
观察到 const * const * cpp =&是正确的; p
是安全的,因为这样可以防止 * cpp =& c
,但这是一个非常模糊的情况,因此标准中未涉及。
It's correct to observe that const *const *cpp = &p
is safe because then *cpp = &c
is prevented, but this is a sufficiently obscure case that it's not covered in the standard.
结论:您可以并且应该自己转换为 const double * const *
。
Conclusion: you can and should cast to const double *const *
yourself.
请注意,使用长度为 n * n的
double *
类型的单个数组会更有效。 code>并做任何必要的数组索引操作: d [i] [j]
变为 d [i * n + j]
。
Note that it would be more efficient to use a single array of type double *
with length n * n
and do any necessary array indexing yourself: d[i][j]
becomes d[i * n + j]
.
这篇关于接受const 2d数组的C函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!