如何将2d数组传递给函数?

时间:2016-07-16 07:11:28

标签: c arrays

此代码按预期工作 - 它会打印数组中的所有整数,但会产生警告。我想知道如何正确行事并避免警告。

#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函数只接受具有指定列数的数组是不可接受的。

4 个答案:

答案 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_rowsnum_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)

指针是一个指针。只要您知道如何在函数中解释警告,就可以忽略/禁止警告。 当然,这样做的首选方法是在两端使用匹配类型。