题目是大概如下:
后来去看了一下书里的参考答案,感觉有点不大对(但是没有验证过)。原型给的好像就不大对,这个原型:
void matrix_multiply(int *m1, int *m2, int *r, int x, int y, int z);
一般如果在参数里面是指针数组的话,需要指明这个指针指向的数组的大小,例如int(*m1)[10] ,所以对于题目给出的原型比较疑惑,而参考答案也没有那样做。参考答案也和题目本身的原型不一样,把int *r改成了register类型。所以我感觉把原型改了,只要出来的结果一样,也算解答对了。当然效率问题以后再说(等学完汇编)
因为可变参数,需要先声明数组大小的int(根据刚学的《C Primer Plus》,所以我给出的原型:
void matrix_mutiplay(int x, int y, int z, int (*m1)[y], int (*m2)[z], int (*r)[z]);
矩阵相乘以前是学过,现在差不多都忘光了。好在根据题目,大概能猜出意思。
看一个3X2的矩阵 与一个 2X 4 的矩阵相乘 ,这里前一个矩阵的列要和 后一个矩阵的行相等,不然就不配了, 就会生成一个3X4的矩阵。 然后这个3X4的矩阵地每个元素, 就是对应元素相乘后的和,例如(00,01的前一个矩阵,和00,10的后一个矩阵相配,然后后一个矩阵的00位置上的数等于 00*00 + 01 * 10 ).
根据生成矩阵的结果,来一个3X4的两层循环,然后考虑每个元素是怎么得来的。
void matrix_mutiplay(int x, int y, int z, int (*m1)[y], int (*m2)[z], int (*r)[z]){
int i,j, k;
for(i = 0 ; i < x ; i++){
for(j = 0 ; j < z ; j++){
for(k = 0 ;k < y ; k++){
*(*(r + i)+ j ) += (*(*(m1+i)+ k))* (*(*(m2 + k) + j));
}
}
}
}
最内层循环就是当i=0,j=0(对应 r矩阵 0,0位置), 当k=0,就是 00*00 ,当k =1 ,就是 01* 10 (因为y = 2)
初始化 m1,m2 后测试
#include <stdio.h>
void matrix_mutiplay(int x, int y, int z, int (*m1)[y], int (*m2)[z], int (*r)[z]);
int main(int argc, const char *argv[])
{
int m1[3][2] = {
{2, -6},
{3, 5},
{1, -1}
};
int m2[2][4] = {
{4,-2,-4,-5},
{-7,-3,6,7}
};
int r[3][4] = {
{0},
{0},
{0}
};
matrix_mutiplay(3, 2, 4, m1, m2, r);
int i ,j;
for(i = 0 ; i < 3; i++){
for(j = 0 ;j < 4; j++){
printf("%d ", *(*(r + i)+j));
}
puts("");
}
return 0;
}
void matrix_mutiplay(int x, int y, int z, int (*m1)[y], int (*m2)[z], int (*r)[z]){
int i,j, k;
for(i = 0 ; i < x ; i++){
for(j = 0 ; j < z ; j++){
for(k = 0 ;k < y ; k++){
*(*(r + i)+ j ) += (*(*(m1+i)+ k))* (*(*(m2 + k) + j));
}
}
}
}
得到的结果和书中的一样:
50 14 -44 -52
-23 -21 18 20
11 1 -10 -12
顺便说一下编译过程中出现错误
/usr/bin/ld: /usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crti.o: unrecognized relocation (0x2b) in section `.init'
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
看意思是链接过程出现错误,根据网上的建议升级了一下gnu的版本。
sudo apt-get install binutils,然后就解决了。