问题描述
背景
我正在编写计算流体动力学代码,我在其中处理向量和矩阵。因此,我想每隔一段时间将它们传递给函数。
在整个代码中,向量和矩阵的内存分配如下
double* vec = calloc(n,sizeof(double));
double* mat = calloc(n * m,sizeof(double));
意思是我想访问这样的矩阵 mat[i * m + j]
。
为了“自动记录”函数,我想将这些数组的大小包含在函数原型中。对于矢量,这完美无缺,看起来像这样
// vecmat.h
void vec_print(size_t n,double const vec[restrict n]);
// vecmat.c
void vec_print(size_t n,double const vec[restrict n])
{
for (size_t i = 0; i < n; ++i) {
printf(DBL_FMT,vec[i]);
}
putchar('\n');
}
问题
为了保持一致,我想对矩阵做同样的事情,所以我这样做了
// vecmat.h
void mat_print(size_t n,size_t m,double const mat[restrict n * m]);
// vecmat.c
void mat_print(size_t n,double const mat[restrict n * m])
{
for (size_t i = 0; i < n; ++i) {
for (size_t j = 0; j < m; ++j) {
printf(DBL_FMT,mat[i * m + j]);
}
putchar('\n');
}
putchar('\n');
}
问题来了。编译时,我收到以下警告
src/vecmat.c:21:49: warning: argument 3 of type ‘const double[restrict n * m]’ declared with mismatched bound ‘n * m’ [-Wvla-parameter]
21 | void mat_print(size_t n,double const mat[restrict n * m])
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from src/vecmat.c:1:
src/vecmat.h:16:49: note: prevIoUsly declared as ‘const double[restrict n * m]’ with bound ‘n * m’
16 | void mat_print(size_t n,double const mat[restrict n * m]);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
代码编译得很好,也产生了预期的输出,但我想去掉警告信息。 我知道 C 不使用提供的数组维度 n * m
,而是默默地将参数转换为 double* restrict mat
。这个问题似乎与我使用乘法和 gcc
以某种方式认为数组边界不一致的事实有关。
问题
我能否以某种方式修改我的语法以避免此编译器警告,或者我可以以某种方式完全禁用 gcc
中的此警告? (gcc
没有标志 -Wno-vla-parameter
)
EDIT -Wno-vla-parameter
确实存在并删除了警告
解决方案
应按如下方式分配矩阵:
double (*mat)[m] = calloc(n * sizeof(*mat));
void mat_print(size_t n,double const mat[restrict n][m]);
这使得以更简单的形式 mat[i][j]
访问矩阵元素成为可能。
不幸的是 gcc 仍然抱怨,因为该函数使用了 const
。 (https://godbolt.org/z/6xh5Exsff) 如果这也有一个巧妙的修复,我的初始和所有后续问题都将得到解决:D
其他资源:
附加信息
-
gcc
版本 11.1.0 -std=c99
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)