1

我是 C 新手(但在经历了一些成长的痛苦之后开始喜欢它),但我在发送矩阵时遇到了一些麻烦。我开始在我的主要功能中构建所有东西,并且它起作用了。我创建了这样的列表:int list[sizeOfBuckets][30];然后添加数据,当我想阅读它时,我做了这样的事情:

    int x;
    int xx;
    for (x=0;x<sizeof(current_list) / sizeof(current_list[0]); x++) {
        printf("we are in the list \n");
        for (xx=0;xx<sizeof(current_list[x]) / sizeof(current_list[x][0]); xx++) {
            printf("item: %i \n", current_list[x][xx]);
        } 
    }

它工作得很好,它会给我矩阵的内容。但现在我想将它发送到一个函数,但我遇到了问题。我做了一些阅读并了解到矩阵与发送数组不同,因为 C 需要事先知道尺寸,但由于我将动态更改,我创建了两个变量来监视两者的大小并将它们发送到数组(在我的测试我验证它们是正确的,列表是列表[2][30])。这是我的功能:

void process_list(int **current_list, int num_of_rows, int num_items_in_row) {
    printf("hello from function \n");
    //test the list
    int x;
    int xx;
    for (x=0;x<num_of_rows; x++) {
        printf("we are in the list \n");
        for (xx=0;xx<num_items_in_row; xx++) {
            printf("item: %i \n", current_list[x][xx]);
        } 
    }
}

它对我不起作用。它只是打印出来we are in the list,而不是我所期望的实际项目(来自下面的 for 循环)。当我使用 GCC 编译时,我收到以下警告:

./learningC.c: In function ‘main’:
./learningC.c:169: warning: passing argument 1 of ‘process_list’ from incompatible pointer type

我想知道我做错了什么?如果有帮助,我不需要修改数组,我只需要将内容发送到函数,然后我的函数将输出不同的结果。

更新:这是我要发送的矩阵:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 4],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 2, 4],

这是预期的结果:

hello from function 
we are in the list 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 2 
item: 2 
item: 2 
item: 4 
we are in the list 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 1 
item: 1 
item: 2 
item: 2 
item: 4 
we are in the list 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 0 
item: 1 
item: 2 
item: 1 
item: 2 
item: 4 
4

5 回答 5

5

如果你有一个现代 C 编译器,从 C99 开始,你可以像这样传递一个可变长度的矩阵(技术术语是“VLA”)

void process_list(size_t num_of_rows, size_t num_items_in_row, int current_list[num_of_rows][num_items_in_row]) {
... access the elements as current_list[i][j] here ...
}

只需注意您在数组之前有大小,以便在数组参数的声明中知道它们。

顺便说一句,您尝试这样做**是不正确的。2D 矩阵和指针数组确实是不同的东西。

于 2012-06-03T23:08:46.993 回答
3

n 维数组仍然是一维内存空间的数组。所以只使用一个指针,而不是指向指针的指针。

void process_list(int *current_list, int num_of_rows, int num_items_in_row) {
    printf("hello from function \n");
    //test the list
    int x;
    int xx;
    for (x=0;x<num_of_rows; x++) {
        printf("we are in the list \n");
        for (xx=0;xx<num_items_in_row; xx++) {
            printf("item: %i \n", current_list[x*num_items_in_row + xx]); % previously it was x*num_of_rows + xx
        } 
    }
}

我还改变了访问元素的方式。现在你必须像这样调用函数:

process_list(*current_list,3,3);
于 2012-06-03T22:26:34.653 回答
2

有很多方法可以传递二维数组。我将首先介绍其中的一些示例,然后指出您代码中的基本错误:

/*
 * Array with empty first dimension.
 * Note the y value passed is redundant in this case.
 */
void process_matrix(int matrix[][4], int x, int y)
{
    for(int i = 0; i < x; i++) {
        for(int j = 0; j < y; j++) {
            printf("[%d][%d] = %d\n", i, j, matrix[i][j]);
        }

        puts("");
    }
}

该函数接收一个第一维为空的数组。这允许传入您声明的未知大小。y在这种情况下,这是多余的,因为我们可以使用诸如ARRAY_SIZE.

/*
 * Pointer to array with explicitly specified second dimension.
 * Again the y value passed is redundant in this case.
 */
void process_matrix2(int (* matrix)[4], int x, int y)
{
    for(int i = 0; i < x; i++) {
        for(int j = 0; j < y; j++) {
            printf("[%d][%d] = %d\n", i, j, matrix[i][j]);
        }

        puts("");
    }
} 

这是一个指向明确指定第二维的数组的指针。请注意在这种情况下非常重要的括号。没有括号的相同代码仍然是有效的 C 但意味着完全不同的东西。通过与上述类似的参数,y参数是多余的。

/*
 * Both dimensions known.
 * Note the x and y value passed are both redundant in this case.
 */
void process_matrix3(int matrix[2][4], int x, int y)
{
    for(int i = 0; i < x; i++) {
        for(int j = 0; j < y; j++) {
            printf("[%d][%d] = %d\n", i, j, matrix[i][j]);
        }

        puts("");
    }
}

此案例可能不适用于您,但出于完整性考虑。如果两个维度都已知,则可以将它们指定为函数原型的一部分。通过与上述类似的论点,x这里y是多余的。

上面的函数可以用这段代码测试(确保用 编译-std=c99):

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int matrix[2][4] = {{1,2,3,4}, {8,7,6,5}};

    process_matrix(matrix, 2, 4);
    process_matrix2(matrix, 2, 4);
    process_matrix3(matrix, 2, 4);
    process_matrix4(matrix, 2, 4);
    return EXIT_SUCCESS;
}

回到您的原始代码,您遇到的问题是双指针不能用作二维数组。引用这篇文章,你当然应该阅读:

...声明:“int **mat”然后将“mat”用作二维数组是错误的。这是两种截然不同的数据类型,使用它们可以访问内存中的不同位置。在一台好的机器(例如 VAX/VMS)上,这个错误会以“内存访问冲突”错误中止程序。

这个错误很常见,因为很容易忘记衰减约定不能递归(多次)应用于同一个数组,因此二维数组不等同于双指针。“指向 T 指针的指针”不能用作“T 的二维数组”。二维数组“等价于”“指向 T 行的指针”,这与“指向 T 的指针”非常不同。

这篇文章展示了一些我没有展示的传递 2D 数组的方法,例如通过展平数组来实现,这是Seçkin Savaşçı试图展示的。

于 2012-06-03T22:57:57.923 回答
2

C 中静态分配的多维数组和动态分配的多维数组之间有一些细微的区别,我不确定我是否准确地记住了它们。也就是说,我认为矩阵的正确类型实际上是指向一维 30 元素整数数组的指针。尝试将您的函数声明更改为:void process_list(int current_list[][30], int num_of_rows, int num_items_in_row),或者也许void process_list(int *current_list[30], int num_of_rows, int num_items_in_row).

于 2012-06-03T22:58:18.973 回答
0

我完全赞成将静态数组视为对象与指针。但是,在涉及对现有代码的补救措施的情况下,可以[小心地]应用一些 C 转换技巧。

在将静态数组传递给 process_list 函数的原始示例中,可以这样做:

int **arrptr;
int static_arr[3][4] = {...};  /* init static array */
...
*arrptr = (int *)&static_arr;    /* put the static_arr address into arrptr */

process_list(arrptr, num_rows,num_cols);

这有效地将静态数组视为经过 malloc 处理,即指针 arrptr 包含对 static_arr 内存地址的引用,而不是在编译时分配的实际地址。

注意:我不提倡这种技术,如果在代码中应用,应该提供一些关于演员意图的评论。否则,有人可能会在不知不觉中尝试“释放”此类指针,以及范围问题等。

于 2012-06-08T21:12:29.573 回答