我是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
答案 0 :(得分: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矩阵和指针数组实际上是不同的东西。
答案 1 :(得分:3)
n维数组仍然是1维存储空间的数组。所以只使用指针,而不是指向指针的指针。
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);
答案 2 :(得分:2)
传递2D数组的方法有很多种。我将首先回顾一些这些例子,然后指出代码中的基本错误:
/*
* 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;
}
回到原始代码,你遇到的问题是双指针不能用作2D数组。引用this article,你当然应该读到:
...声明:“int ** mat”然后使用“mat”作为2D是错误的 阵列。这是两种截然不同的数据类型并使用它们 访问内存中的不同位置。在一台好机器上(例如VAX / VMS) 这个错误以“内存访问冲突”中止程序 错误。
这个错误很常见,因为很容易忘记腐烂 约定不得以递归方式(不止一次)应用于相同的方法 数组,因此2D数组不等同于双指针。一个 “指向T的指针”不能用作“T的2D数组”。 2D 数组与“指向T行的指针”“等价”,这是非常的 不同于“指向T指针”。
本文展示了一些传递2D数组的方法,我没有展示这些方法,例如通过展平数组来实现它,这就是Seçkin Savaşçı试图显示的内容。
答案 3 :(得分: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)
。
答案 4 :(得分: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'ed,即指针arrptr包含引用到static_arr的内存地址,而不是在编译时分配的实际地址
注意:我不是在提倡这种技术,如果在代码中应用,则应提供有关强制转换意图的一些注释。否则,有人可能会在不知不觉中试图“释放”这样的指针,同时也会出现范围问题等。