I seem to have a problem in getting an element from a two dimensional array in c. It looks very straightforward to me, but I guess one doesn't see his one mistakes :P. I believe that my code is correct, although I do get a warning.
我似乎在从c中的二维数组中获取元素时遇到问题。对我来说这看起来非常简单,但我想有人不会看到他的一个错误:P。我相信我的代码是正确的,虽然我收到警告。
The code:
#include <stdio.h>
#include <stdlib.h>
#include <matrixmath.h>
#define SIZE 2
int main() {
int mat1[SIZE][SIZE] = {{2,3},{4,5}};
int mat2[SIZE][SIZE] = {{6,7},{8,9}};
int *res = multiply(mat1, mat2, SIZE);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = *(*(res + i) + j);
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
The error I get:
我得到的错误:
invalid type argument of unary '*' (have 'int')
一元'*'的无效类型参数(有'int')
Am I not seeing something here?
我在这里看不到什么?
EDIT:
Sorry guys, this is the .h file:
对不起伙计们,这是.h文件:
#define SIZE 2
int* multiply(int mat1[][SIZE], int mat2[][SIZE], int size) {
int res[size][size];
int i,j, k;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
int sumElement = 0;
for (k = 0; k < size; k++) {
sumElement += mat1[i][k]*mat2[k][j];
}
res[i][j] = sumElement;
printf("sumElement: %d\n", sumElement);
}
}
return &res;
}
I also have to add that I define SIZE
here as well, which seems very unlogical. But I have no choice as I have to specify the size the 2D arrays.
我还要补充一点,我也在这里定义SIZE,这看起来非常不合逻辑。但我别无选择,因为我必须指定2D阵列的大小。
3 个解决方案
#1
Functions in C cannot return matrixes directly, you would have to use double pointers. An array with pointers to each array corresponding to a line of matrix.
C中的函数不能直接返回矩阵,你必须使用双指针。一个数组,指向每个数组,对应一行矩阵。
This adds rather unecessary complication to your problem, though, and would require allocating memory to the returned buffer which is something to be avoided (and also you can't return a pointer to a local variable, it will crash).
这会给你的问题增加相当不必要的复杂性,并且需要将内存分配给返回的缓冲区,这是要避免的(并且你也不能返回指向局部变量的指针,它会崩溃)。
I believe the best solution in your case, is to not return any value at all. Simply provide multiply()
with a buffer it can use to store the results:
我相信在你的情况下,最好的解决方案是不返回任何价值。只需为multiply()提供一个可用于存储结果的缓冲区:
#define SIZE 2
void multiply(int res[SIZE][SIZE], int mat1[SIZE][SIZE], int mat2[SIZE][SIZE])
{
int i, j, k, sumElement;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
sumElement = 0;
for (k = 0; k < SIZE; k++) {
sumElement += mat1[i][k] * mat2[k][j];
}
res[i][j] = sumElement;
printf("sumElement: %d\n", sumElement);
}
}
}
And use the function like this:
并使用这样的功能:
int main()
{
int mat1[SIZE][SIZE] = {{2,3},{4,5}};
int mat2[SIZE][SIZE] = {{6,7},{8,9}};
int res[SIZE][SIZE];
multiply(res, mat1, mat2);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
Note that native matrixes are not very versatile and can be a tricky thing to to pass as paramter to other functions, because the function will have to know the dimensions of this matrix at compile time otherwise it won't work. The only way to make a function that can handle matrixes of any dimension is making it work with double pointers.
请注意,原生矩阵不是非常通用,并且作为参数传递给其他函数可能是一件棘手的事情,因为该函数必须在编译时知道该矩阵的维度,否则它将无法工作。创建一个可以处理任何维度矩阵的函数的唯一方法是使它可以使用双指针。
Answering comment:
To convert them into pointer to pointer and be able to pass matrixes of any size to your function and allow this function to return a matrix aswell, you would have to do something like this:
要将它们转换为指针指针并能够将任何大小的矩阵传递给您的函数并允许此函数返回矩阵,您还必须执行以下操作:
int** multiply(int** mat1, int** mat2, int size)
{
int i, j, k;
// allocate the memory necessary to store the results
int** res = malloc(size * sizeof(int*));
for (i = 0; i < size; ++i)
res[i] = malloc(size * sizeof(int));
// populate res with values
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
{
res[i][j] = 0;
for (k = 0; k < size; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
printf("sumElement: %d\n", res[i][j]);
}
return res;
}
Now this function can process any matrix of any size, will automatically allocate the memory necessary to store the result, and return a pointer that you can access with res[i][j]
. Usage:
现在这个函数可以处理任何大小的任何矩阵,将自动分配存储结果所需的内存,并返回一个可以用res [i] [j]访问的指针。用法:
int main()
{
int mat1[][SIZE] = { { 2, 3 }, { 4, 5 } };
int mat2[][SIZE] = { { 6, 7 }, { 8, 9 } };
// map them into double pointer matrixes so they can be used by multiply()
int* pmat1[SIZE] = { mat1[0], mat1[1] };
int* pmat2[SIZE] = { mat2[0], mat2[1] };
int** res = multiply(pmat1, pmat2, SIZE);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
There is only one problem with this code, it is considered bad practice to allocate memory that won't be released before the end of the same function. Instead, main()
should allocate the memory used by res
and pass this buffer to multiply()
to use, and also be responsable of releasing this memory after its used. Not releasing memory you no longer need is a problem known as memory leak. Read the wikipedia artigle for details.
这段代码只有一个问题,分配在同一函数结束之前不会释放的内存被认为是不好的做法。相反,main()应分配res使用的内存并将此缓冲区传递给multiply()以使用,并且还负责在使用后释放此内存。不释放您不再需要的内存是一个称为内存泄漏的问题。阅读*artigle了解详情。
In such a simple code where the program will terminate shortly after computing the matrix it is not important, but you should keep this in mind for future projects.
在这样一个简单的代码中,程序将在计算矩阵后不久终止它并不重要,但是你应该记住这一点以备将来的项目使用。
Update 2:
This is one way to do that:
这是一种方法:
void multiply(int** res, int** mat1, int** mat2, int size)
{
int i, j, k;
// populate res with values
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
{
res[i][j] = 0;
for (k = 0; k < size; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
printf("sumElement: %d\n", res[i][j]);
}
}
int main()
{
int mat1[][SIZE] = { { 2, 3 }, { 4, 5 } };
int mat2[][SIZE] = { { 6, 7 }, { 8, 9 } };
int res[][SIZE] = { { 0, 0 }, { 0, 0 } };
// map them into double pointer matrixes so they can be used by multiply()
int* pmat1[SIZE] = { mat1[0], mat1[1] };
int* pmat2[SIZE] = { mat2[0], mat2[1] };
int* pres[SIZE] = { res[0], res[1] };
multiply(pres, pmat1, pmat2, SIZE);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
#2
The problem here is with the variable
这里的问题是变量
int *res =....
res
is of type int *
. So, for a statement like
res的类型为int *。所以,对于像这样的陈述
*(*(res + i) + j);
-
*(res + i)
givesint
. -
*(res + i) + j
also gives anint
*(res + i)给出int。
*(res + i)+ j也给出了一个int
and, that int
value is not eligible to be used as the operand of unary *
operator. Hence the error.
并且,该int值不能用作一元*运算符的操作数。因此错误。
EDIT:
Your multiply()
invokes undefined behavior as it return
s the address of a local variable. In other words, after the multiply()
finishes execution, the existence of res
ceases and trying to access the returned value is UB. You should use dynamic memory allocation [malloc()
/calloc()
] instead.
multiply()调用未定义的行为,因为它返回局部变量的地址。换句话说,在multiply()完成执行之后,res的存在并尝试访问返回的值是UB。您应该使用动态内存分配[malloc()/ calloc()]。
Moreover, the return
type and the return
value does not match.
而且,返回类型和返回值不匹配。
That said, header files should ideally contain function declaration (prototype), not function definition.
也就是说,头文件理想情况下应该包含函数声明(原型),而不是函数定义。
#3
Firstly never define array as function parameters because this is misleading (they 'magically' adjust into pointer).
首先,永远不要将数组定义为函数参数,因为这是误导性的(它们“神奇地”调整为指针)。
What I mean is that this:
我的意思是:
int* multiply(int mat1[][SIZE], int mat2[][SIZE], int size)
Automatically became this:
自动成为这个:
int* multiply(int (*mat1)[SIZE], int (*mat2)[SIZE], int size)
Which is not what you want obviously as this way modifying those parameters actually modifies the argument passed and this is not 'pass by value' what the syntax suggests.
这显然不是你想要的,因为修改这些参数实际上修改了传递的参数,这不是语法建议的“按值传递”。
Second pointer to 2 dimensional array of 'SIZE' is written as following:
第二个指向“SIZE”二维数组的指针如下:
int (*)[SIZE][SIZE]
and not:
int *
So your whole code is very wrong. Here I'll put the right version of it:
所以你的整个代码都是非常错误的。在这里,我将把它的正确版本:
#define SIZE 2
struct _2dimensarrayofSIZE { int d[SIZE][SIZE]; }; //*1
struct _2dimensarrayofSIZE multiply(int (*pmat1)[SIZE][SIZE], int (*pmat2)[SIZE][SIZE]) {
struct _2dimensarrayofSIZE res;
int i,j, k;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
int sumElement = 0;
for (k = 0; k < size; k++) {
sumElement += (*pmat1)[i][k]*(*pmat2)[k][j];
}
res.d[i][j] = sumElement;
printf("sumElement: %d\n", sumElement);
}
}
return res;
}
And the main source:
主要来源:
#include <stdio.h>
#include <stdlib.h>
#include <matrixmath.h> //
//#define SIZE 2 supposing that this is defined in your 'multiply'
//function header
int main() {
int mat1[SIZE][SIZE] = {{2,3},{4,5}};
int mat2[SIZE][SIZE] = {{6,7},{8,9}};
struct _2dimensarrayofSIZE res = multiply(&mat1, &mat2); //*2
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = *(*(res.d + i) + j);
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
Notes:
*1: Here we use an array into structure hack because otherwise 'C' doesn't allow us to return arrays.
* 1:这里我们使用数组进入结构hack,否则'C'不允许我们返回数组。
*2: Here we pass two-dimensional arrays pointer by using '&' (address operator).
* 2:这里我们使用'&'(地址运算符)传递二维数组指针。
#1
Functions in C cannot return matrixes directly, you would have to use double pointers. An array with pointers to each array corresponding to a line of matrix.
C中的函数不能直接返回矩阵,你必须使用双指针。一个数组,指向每个数组,对应一行矩阵。
This adds rather unecessary complication to your problem, though, and would require allocating memory to the returned buffer which is something to be avoided (and also you can't return a pointer to a local variable, it will crash).
这会给你的问题增加相当不必要的复杂性,并且需要将内存分配给返回的缓冲区,这是要避免的(并且你也不能返回指向局部变量的指针,它会崩溃)。
I believe the best solution in your case, is to not return any value at all. Simply provide multiply()
with a buffer it can use to store the results:
我相信在你的情况下,最好的解决方案是不返回任何价值。只需为multiply()提供一个可用于存储结果的缓冲区:
#define SIZE 2
void multiply(int res[SIZE][SIZE], int mat1[SIZE][SIZE], int mat2[SIZE][SIZE])
{
int i, j, k, sumElement;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
sumElement = 0;
for (k = 0; k < SIZE; k++) {
sumElement += mat1[i][k] * mat2[k][j];
}
res[i][j] = sumElement;
printf("sumElement: %d\n", sumElement);
}
}
}
And use the function like this:
并使用这样的功能:
int main()
{
int mat1[SIZE][SIZE] = {{2,3},{4,5}};
int mat2[SIZE][SIZE] = {{6,7},{8,9}};
int res[SIZE][SIZE];
multiply(res, mat1, mat2);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
Note that native matrixes are not very versatile and can be a tricky thing to to pass as paramter to other functions, because the function will have to know the dimensions of this matrix at compile time otherwise it won't work. The only way to make a function that can handle matrixes of any dimension is making it work with double pointers.
请注意,原生矩阵不是非常通用,并且作为参数传递给其他函数可能是一件棘手的事情,因为该函数必须在编译时知道该矩阵的维度,否则它将无法工作。创建一个可以处理任何维度矩阵的函数的唯一方法是使它可以使用双指针。
Answering comment:
To convert them into pointer to pointer and be able to pass matrixes of any size to your function and allow this function to return a matrix aswell, you would have to do something like this:
要将它们转换为指针指针并能够将任何大小的矩阵传递给您的函数并允许此函数返回矩阵,您还必须执行以下操作:
int** multiply(int** mat1, int** mat2, int size)
{
int i, j, k;
// allocate the memory necessary to store the results
int** res = malloc(size * sizeof(int*));
for (i = 0; i < size; ++i)
res[i] = malloc(size * sizeof(int));
// populate res with values
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
{
res[i][j] = 0;
for (k = 0; k < size; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
printf("sumElement: %d\n", res[i][j]);
}
return res;
}
Now this function can process any matrix of any size, will automatically allocate the memory necessary to store the result, and return a pointer that you can access with res[i][j]
. Usage:
现在这个函数可以处理任何大小的任何矩阵,将自动分配存储结果所需的内存,并返回一个可以用res [i] [j]访问的指针。用法:
int main()
{
int mat1[][SIZE] = { { 2, 3 }, { 4, 5 } };
int mat2[][SIZE] = { { 6, 7 }, { 8, 9 } };
// map them into double pointer matrixes so they can be used by multiply()
int* pmat1[SIZE] = { mat1[0], mat1[1] };
int* pmat2[SIZE] = { mat2[0], mat2[1] };
int** res = multiply(pmat1, pmat2, SIZE);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
There is only one problem with this code, it is considered bad practice to allocate memory that won't be released before the end of the same function. Instead, main()
should allocate the memory used by res
and pass this buffer to multiply()
to use, and also be responsable of releasing this memory after its used. Not releasing memory you no longer need is a problem known as memory leak. Read the wikipedia artigle for details.
这段代码只有一个问题,分配在同一函数结束之前不会释放的内存被认为是不好的做法。相反,main()应分配res使用的内存并将此缓冲区传递给multiply()以使用,并且还负责在使用后释放此内存。不释放您不再需要的内存是一个称为内存泄漏的问题。阅读*artigle了解详情。
In such a simple code where the program will terminate shortly after computing the matrix it is not important, but you should keep this in mind for future projects.
在这样一个简单的代码中,程序将在计算矩阵后不久终止它并不重要,但是你应该记住这一点以备将来的项目使用。
Update 2:
This is one way to do that:
这是一种方法:
void multiply(int** res, int** mat1, int** mat2, int size)
{
int i, j, k;
// populate res with values
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
{
res[i][j] = 0;
for (k = 0; k < size; k++)
res[i][j] += mat1[i][k] * mat2[k][j];
printf("sumElement: %d\n", res[i][j]);
}
}
int main()
{
int mat1[][SIZE] = { { 2, 3 }, { 4, 5 } };
int mat2[][SIZE] = { { 6, 7 }, { 8, 9 } };
int res[][SIZE] = { { 0, 0 }, { 0, 0 } };
// map them into double pointer matrixes so they can be used by multiply()
int* pmat1[SIZE] = { mat1[0], mat1[1] };
int* pmat2[SIZE] = { mat2[0], mat2[1] };
int* pres[SIZE] = { res[0], res[1] };
multiply(pres, pmat1, pmat2, SIZE);
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = res[i][j];
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
#2
The problem here is with the variable
这里的问题是变量
int *res =....
res
is of type int *
. So, for a statement like
res的类型为int *。所以,对于像这样的陈述
*(*(res + i) + j);
-
*(res + i)
givesint
. -
*(res + i) + j
also gives anint
*(res + i)给出int。
*(res + i)+ j也给出了一个int
and, that int
value is not eligible to be used as the operand of unary *
operator. Hence the error.
并且,该int值不能用作一元*运算符的操作数。因此错误。
EDIT:
Your multiply()
invokes undefined behavior as it return
s the address of a local variable. In other words, after the multiply()
finishes execution, the existence of res
ceases and trying to access the returned value is UB. You should use dynamic memory allocation [malloc()
/calloc()
] instead.
multiply()调用未定义的行为,因为它返回局部变量的地址。换句话说,在multiply()完成执行之后,res的存在并尝试访问返回的值是UB。您应该使用动态内存分配[malloc()/ calloc()]。
Moreover, the return
type and the return
value does not match.
而且,返回类型和返回值不匹配。
That said, header files should ideally contain function declaration (prototype), not function definition.
也就是说,头文件理想情况下应该包含函数声明(原型),而不是函数定义。
#3
Firstly never define array as function parameters because this is misleading (they 'magically' adjust into pointer).
首先,永远不要将数组定义为函数参数,因为这是误导性的(它们“神奇地”调整为指针)。
What I mean is that this:
我的意思是:
int* multiply(int mat1[][SIZE], int mat2[][SIZE], int size)
Automatically became this:
自动成为这个:
int* multiply(int (*mat1)[SIZE], int (*mat2)[SIZE], int size)
Which is not what you want obviously as this way modifying those parameters actually modifies the argument passed and this is not 'pass by value' what the syntax suggests.
这显然不是你想要的,因为修改这些参数实际上修改了传递的参数,这不是语法建议的“按值传递”。
Second pointer to 2 dimensional array of 'SIZE' is written as following:
第二个指向“SIZE”二维数组的指针如下:
int (*)[SIZE][SIZE]
and not:
int *
So your whole code is very wrong. Here I'll put the right version of it:
所以你的整个代码都是非常错误的。在这里,我将把它的正确版本:
#define SIZE 2
struct _2dimensarrayofSIZE { int d[SIZE][SIZE]; }; //*1
struct _2dimensarrayofSIZE multiply(int (*pmat1)[SIZE][SIZE], int (*pmat2)[SIZE][SIZE]) {
struct _2dimensarrayofSIZE res;
int i,j, k;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
int sumElement = 0;
for (k = 0; k < size; k++) {
sumElement += (*pmat1)[i][k]*(*pmat2)[k][j];
}
res.d[i][j] = sumElement;
printf("sumElement: %d\n", sumElement);
}
}
return res;
}
And the main source:
主要来源:
#include <stdio.h>
#include <stdlib.h>
#include <matrixmath.h> //
//#define SIZE 2 supposing that this is defined in your 'multiply'
//function header
int main() {
int mat1[SIZE][SIZE] = {{2,3},{4,5}};
int mat2[SIZE][SIZE] = {{6,7},{8,9}};
struct _2dimensarrayofSIZE res = multiply(&mat1, &mat2); //*2
int i, j;
for(i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++) {
int getEl = *(*(res.d + i) + j);
printf("%d ", getEl);
}
printf("\n");
}
return 0;
}
Notes:
*1: Here we use an array into structure hack because otherwise 'C' doesn't allow us to return arrays.
* 1:这里我们使用数组进入结构hack,否则'C'不允许我们返回数组。
*2: Here we pass two-dimensional arrays pointer by using '&' (address operator).
* 2:这里我们使用'&'(地址运算符)传递二维数组指针。