尝试在C中为任意大小的矩阵编写矩阵乘法函数。我正在尝试以下函数签名:
void matrixMult(void *A, int Xa, int Ya, void *B, int Xb, int Yb);
(现在它在我排除故障时返回无效状态,一旦我按照我想要的方式工作,我会稍后返回)
X和Y参数用于告知函数传入数组的维度(根据我的理解,这是必要的,因为在C数组中不知道它们自己的大小)。所以我传递了两个无效指针A和B,以及它们的尺寸。
我的问题:一旦我进入函数,我该如何将void指针转换回int数组,以便我可以读取它们?我尝试了以下方法:
(int)*A[someX][someY]
,但是我收到有关“无效使用void指针”的编译器错误。
修改
以下是我现在的全部功能(更新时我正在排除故障):
#pragma warning(disable: 8057)
#include <stdio.h>
void matrixMult(int **A, int Xa, int Ya, int **B, int Xb, int Yb);
int main(int argc, char *argv[]) {
// [x][y] x--> row; y-->cols
int a[3][5] = {
{ 1, 2, 3, 4, 5 }
, { 10, 20, 30, 40, 50 }
, { 4, 8, 15, 16, 23 }
};
int b[5][7] = {
{ 1, 2, 3, 4, 5, 6, 7 }
, { 10, 20, 30, 40, 50, 60, 70 }
, { 4, 8, 15, 16, 23, 42, 0 }
, { 1, 2, 3, 4, 5, 6, 7 }
, { 10, 20, 30, 40, 50, 60, 70 }
};
matrixMult((int **)a, 3, 5, (int **)b, 5, 7);
printf("done\n");
return 0;
}
void matrixMult(int **A, int Xa, int Ya, int **B, int Xb, int Yb) {
printf("starting matrix mult\n");
int i, j;
for (i=0; i<Xa; i++) {
for (j=0; j<Ya; j++) {
//printf("%i, %i:\t", i, j);
printf("%i\t", A[Ya*i+j]);
}
printf("\n");
}
}
编辑2 感谢您的提示和资源!上面发布的版本的工作方式与我现在的预期相同,但我担心如何使用指针是一个丑陋的混蛋。现在我要去做一些关于指针的阅读(感谢cnicutar!),我稍后会再看一遍。我对最新版本的任何进一步批评表示赞赏,但我现在已经回答了这个问题并继续进行了进一步的阅读。再次感谢!
答案 0 :(得分:5)
如果我理解你的问题,你可以做类似的事情
int **a = A;
为什么您要立即使用void *
而不是int **A
?
根据以下评论:请参阅this FAQ entry(f3
是您想要的)。还有this one。
声明并初始化它们(像这样):
int **a;
a = malloc(sizeof(*a) * 3);
for (i = 0; i < 3; i++) {
a[i] = malloc(sizeof(int) * 5);
}
答案 1 :(得分:3)
原型必须是双指针。此外,您不需要取消引用(除非您的内部指针本身是指针本身),因为您将它转换为int。除非类型是int *。
void matrixMult(void **A, int Xa, int Ya, void **B, int Xb, int Yb);
无需取消引用,因为它只是一个基本的int。
(int)A[someX][someY]
如果你有,让我们说一个int *你需要取消引用它,但即使这样你也会在演员之外取消引用
*(int *)A[someX][someY]
在取消引用指针之前,必须让编译器知道类型是什么。否则,您将错误地尝试取消引用void *。
答案 2 :(得分:1)
如果您有C99,您可以简单地使用可变长度数组,它们是为它而制作的。忘记指针的指针,然后做
void matrixMult(size_t n, size_t m, size_t k, double A[n][m], double B[m][k], double C[n][k]);
重要的是,尺寸首先出现在参数列表中,以便在A
,B
和C
时知道它们。在函数内部,您可以通过类似A[i][j]
的内容访问各个矩阵元素。
然后要分配这样的矩阵,你必须要小心,不要在堆栈上分配它们。 E.g
double (*A)[n][m] = malloc(*A);
应该这样做。
真的试着忘记将矩阵定义为指针数组,对于每个指针,你必须分配它自己的块,依此类推。这很复杂,容易出错,并增加了不必要的间接水平。
答案 3 :(得分:0)
void*
不是某种模板类型参数。由于您需要将指针强制转换为某种类型,即指针指向的数据类型,并且整个操作是针对该类型编译的,因此单独使用void*
指针在这里只是意义不大。可以添加一个参数来告诉传递哪种类型,并相应地在函数中进行分支,或者更好地使用正确的类型并相应地命名函数。此外,您不应该使用双指针:根据内存分配,它可能会破坏缓存局部性。
要保存输入,请使用宏:
#define MATRIXMULT(type, typeshort) void matrixMult##typeshort(\
##type *A, int const Xa, int const Ya, ##type *B, int const Xb, int const Yb)\
{ \
printf("starting matrix mult\n"); \
int i, j, k; \
\
if(Ya != Xb || Xa != Yb) \
return; // dimensions don't match \
\
for (i=0; i<Xa; i++) { \
for (j=0; j<Ya; j++) { \
A[i*Ya + j]=0; \
for(k=0; k < Xa; k++) \
A[i*Ya + j] += A[i*Ya + k] * B[k*Yb + j]; \
} \
}
MATRIXMULT(double, d)
MATRIXMULT(float, f)
MATRIXMULT(int, i)
由于评论而编辑:
MATRIXMULT(double, d)
扩展为
void matrixMultd(
double *A, int const Xa, int const Ya, double *B, int const Xb, int const Yb)
{
printf("starting matrix mult\n");
int i, j, k;
if(Ya != Xb || Xa != Yb)
return;
for (i=0; i<Xa; i++) {
for (j=0; j<Ya; j++) {
A[i*Ya + j]=0;
for(k=0; k < Xa; k++)
A[i*Ya + j] += A[i*Ya + k] * B[k*Yb + j];
}
}
因此,使用宏可以很容易地在多个变体中获得相同的功能。通过上述宏扩展,您可以调用matrixMultd
,matrixMultf
和matrixMulti