gpt4 book ai didi

采用 const 二维数组的 C 函数

转载 作者:太空狗 更新时间:2023-10-29 15:33:24 25 4
gpt4 key购买 nike

我想编写一个 C 函数,将动态二维数组作为输入,但不改变该数组。

我试图使 const 正确,不仅是为了让我的代码更清晰,而且因为我的函数将从 C++ 代码中调用,而 C++ 对这些事情非常挑剔。

我如何声明一个函数来将“const”指针指向一个指针,即我如何表明该函数不会改变二维数组的内容?

下面是一个具体的、 super 简单的例子。我正在使用 2D double 组,即 double**,来表示大小为 n x n 的 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 **'

Actor 克服了这个问题:

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

但是使用强制转换来克服编译器的不便感觉是错误的。

或者,我可以抑制编译器警告,但这是一种逃避。

因此,我希望我的代码能够干净利落地编译,并且我希望在不借助强制转换的情况下将动态二维数组的常量特性传达给函数。这似乎是一个合法的目标。这可能吗?如果不是,执行此操作的标准/公认做法是什么?

最佳答案

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

观察到 const *const *cpp = &p 是安全的是正确的,因为 *cpp = &c 被阻止了,但这是一个足够模糊的情况,它不是包含在标准中。

结论:您可以而且应该自己转换为 const double *const *

请注意,使用长度为 n * ndouble * 类型的单个数组并自己进行任何必要的数组索引会更有效:d [i][j] 变为 d[i * n + j]

关于采用 const 二维数组的 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11014267/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com