我想将二维数组传递给函数,但是,我想用任意大小来做到这一点。
首先请看下面的代码:
#define MAX_ROWS 8
#define MAX_SIZE 32
static void foo(char array[][MAX_SIZE], size_t max_rows, size_t max_size) {
for (size_t i = 0; i < max_rows; i++) {
printf("%s\n", array[i]);
}
}
int main(void) {
char array[MAX_ROWS][MAX_SIZE];
for (size_t i = 0; i < MAX_ROWS; i++) {
snprintf(array[i], MAX_SIZE, "Row: %d", i);
}
foo(array, MAX_ROWS, MAX_SIZE);
return 0;
}
A. 此代码按预期工作。但有一句话我不喜欢:
static void foo(char array[][MAX_SIZE], size_t max_rows, size_t max_size)
我不喜欢它,因为我不仅需要指定最大大小两次,还需要对第二维的最大大小进行硬编码,以使其在编译时可用。
B. 另一种方法是制作可变长度数组(VLA)。为此,我们需要更改参数的顺序,以便
size_t max_size
出现在数组之前:
static void foo(size_t max_rows, size_t max_size, char array[][max_size])
foo(MAX_ROWS, MAX_SIZE, array);
一方面我喜欢这个解决方案,但另一方面我不喜欢它。它是 C99 标准的一部分,但不受 MSVC 支持。因此,我根本无法使用它。
我也不确定是否会因为安全原因而阻止这种使用,即使大小 - 由于使用宏常量 - 仍然事实上是硬编码的,因此实际上不是可变的。
C. 据我了解,
char array[MAX_ROWS][MAX_SIZE]
内部只不过是一个大小为max_rows * max_size * sizeof(char)
的缓冲区。所以我正在考虑以下解决方案,但这会导致Segmentation Fault
:
static void foo(void *array0, size_t max_rows, size_t max_size) {
size_t total_size = max_rows * max_size * sizeof(char);
char *array = malloc(total_size);
memcpy(array, array0, total_size);
for (size_t i = 0; i < max_rows; i++) {
printf("%s\n", array[i]);
}
free(array);
}
您不需要保留空间来访问数组的每个元素,只需对字符使用指针算术,这就是像 qsort 这样的函数在不知道传递数组的具体类型时的做法:
#include <stdio.h>
static void foo(void *array0, size_t max_rows, size_t max_size)
{
char *array = array0;
char *ptr = array;
for (size_t i = 0; i < max_rows; i++) {
printf("%s\n", ptr);
ptr += max_size;
}
}
int main(void)
{
enum {MAX_ROWS = 3, MAX_SIZE = 4};
char array[MAX_ROWS][MAX_SIZE] = {"abc", "cde", "fgh"};
foo(array, MAX_ROWS, MAX_SIZE);
return 0;
}
输出:
abc
cde
fgh