此代码按预期工作 - 它会打印数组中的所有整数,但会产生警告。我想知道如何正确行事并避免警告。
#include <stdio.h>
#include <stddef.h>
void print_all(int * array, ptrdiff_t num_rows, ptrdiff_t num_cols) {
for (ptrdiff_t i = 0; i < num_rows; ++i) {
for (ptrdiff_t j = 0; j < num_cols; ++j) {
printf("%d\n", array[num_cols * i + j]);
}
}
}
int main() {
int array[2][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8}
};
print_all(array, 2, 4);
}
这是警告:
$ clang -Wall -Wextra -pedantic -fsanitize=address -std=c11 arrays.c
arrays.c:18:15: warning: incompatible pointer types passing 'int [2][4]' to
parameter of type 'int *' [-Wincompatible-pointer-types]
print_all(array, 2, 4);
^~~~~
arrays.c:4:22: note: passing argument to parameter 'array' here
void print_all(int * array, ptrdiff_t num_rows, ptrdiff_t num_cols) {
^
1 warning generated.
让print_all
函数只接受具有指定列数的数组是不可接受的。
答案 0 :(得分:4)
如果您的编译器支持variable length arrays(VLA),那么您可以执行此操作
void print_all(ptrdiff_t num_rows, ptrdiff_t num_cols, int array[num_rows][num_cols]) {
for (ptrdiff_t i = 0; i < num_rows; ++i) {
for (ptrdiff_t j = 0; j < num_cols; ++j) {
printf("%d\n", array[i][j]);
}
}
}
int main(void) {
int array[2][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8}
};
print_all(2, 4, array);
}
num_rows
和num_cols
参数必须位于array
参数之前,以便编译器知道数组的尺寸。 VLA允许您使用2D数组索引array[i][j]
而不是自己进行数学运算。
如果您不能使用VLA或不想使用VLA,那么解决方案只是传递2D数组的第一个元素的地址
print_all(&array[0][0], 2, 4);
答案 1 :(得分:2)
2D数组类似于int[rows][cols]
。那么为什么不对函数参数使用相同的语法呢?
void print_all(size_t rows, size_t cols, int array[rows][cols]);
请注意使用维度的正确类型,这不是签名ptrdiff_t
,而是size_t
。您还必须首先声明维度参数,以便它们对于数组声明是已知的。
与大多数数组的使用类似,数组的名称被隐式转换为指向第一个元素的指针,第一个元素本身就是一维数组:int (*)[cols]
。
对元素array[r][c]
使用普通的2D索引运算符。
在数组的参数声明中,外部(rows
)长度实际上不是必需的,可以省略:int array [][cols]
。但无论如何,最好对其进行规范化,这至少是出于文档目的。
整个事情与常数长度数组大致相同。它被称为可变长度数组(VLA,出于显而易见的原因)和标准C,因为C99(C11使其成为可选,但任何现代编译器都应该支持它。)
如果您有一个古老的编译器,请使用带有下面宏的常量长度数组。
<强>旁注:强>
不要使用魔术数字。将main
中数组的维度定义为宏并仅使用宏:
#define ROWS 2
#define COLS 4
...
int main(void)
{
int array[ROWS][COLS] = ...;
print_all(ROWS, COLS, array);
}
(我还使用了main
的正确签名;不推荐使用空参数列表,并且该标准将在未来版本中删除。)
这样,如果要更改尺寸的长度,则只需更改宏。
答案 2 :(得分:1)
您的print_all()
正在接受1D数组,但您的main
正在解析2D数组,因此警告。
您可以保持您的功能完整,并将您的array
更改为1D阵列,它应该可以正常工作。
void print_all(int * array, ptrdiff_t num_rows, ptrdiff_t num_cols) {
for (ptrdiff_t i = 0; i < num_rows; ++i) {
for (ptrdiff_t j = 0; j < num_cols; ++j) {
printf("%d\n", array[num_cols * i + j]);
}
}
}
并在main()
int array[] = {1, 2, 3, 4, 5, 6, 7, 8};
如果您在main
中保留2D数组,那么您需要更改print_all()
void print_all(int array[][4], ptrdiff_t num_rows) {
for (ptrdiff_t i = 0; i < num_rows; ++i) {
for (ptrdiff_t j = 0; j < 4; ++j) {
printf("%d\n", array[i][j]);
}
}
}
并在main
int array[][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8}
};
您必须提供第二维(4),但可以省略第一维(2);这是2D数组在内存中存储的一系列1D数组。
答案 3 :(得分:-3)
指针是一个指针。只要您知道如何在函数中解释警告,就可以忽略/禁止警告。 当然,这样做的首选方法是在两端使用匹配类型。