我的代码如下所示
要调用该函数,代码类似于以下内容:
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[N][1];
int main(void)
{
matrix_multiply((float*) m1, (float*) m2, N, N, 1, (float*) result);
}
void matrix_multiply(float* input_matrix1, float* input_matrix2, int m, int p, int n, float* output_matrix)
{
// Matrix Multiplication Routine
// input_matrix1= input matrix (m x p)
// input_matrix2 = input matrix (p x n)
// m = number of rows in input_matrix1
// p = number of columns in input_matrix1 which should equal the number of rows in input_matrix2
// n = number of columns in input_matrix2
// output_matrix = output matrix = input_matrix1*input_matrix2 (m x n)
//.....Code that does matrix multiplication
}
我还没有遇到过在调用函数时使用 (float*)
。谁能详细描述一下。
最佳答案
符号(float *)X
是一个强制转换。如果矩阵乘法函数在使用之前声明(或定义),那么强制转换是必要的,因为传递给函数的类型不是函数期望的 float *
而是 float (*)[2]
(这是一个指向数组的指针)。强制转换告诉编译器“我们比你更了解这个 C”,尽管这是一个非常有争议的命题。
这是问题中代码的稍微修改版本:
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(float *input_matrix1, float *input_matrix2, int m, int p, int n, float *output_matrix);
int main(void)
{
matrix_multiply( m1, m2, N, N, 1, result);
matrix_multiply(&m1[0][0], &m2[0][0], N, N, 1, &result[0][0]);
matrix_multiply((float*) m1, (float*) m2, N, N, 1, (float*) result);
}
void matrix_multiply(float *input_matrix1, float *input_matrix2, int m, int p, int n, float *output_matrix)
{
// Matrix Multiplication Routine
// input_matrix1 = input matrix (m x p)
// input_matrix2 = input matrix (p x n)
// m = number of rows in input_matrix1
// p = number of columns in input_matrix1 and the number of rows in input_matrix2
// n = number of columns in input_matrix2
// output_matrix = output matrix = input_matrix1*input_matrix2 (m x n)
//.....Code that does matrix multiplication
}
在 Mac OS X 10.8.4 上使用 GCC 4.7.1 编译时,输出为:
$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -c matmul89.c
matmul89.c: In function ‘main’:
matmul89.c:10:5: warning: passing argument 1 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[2]’
matmul89.c:10:5: warning: passing argument 2 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[1]’
matmul89.c:10:5: warning: passing argument 6 of ‘matrix_multiply’ from incompatible pointer type [enabled by default]
matmul89.c:6:6: note: expected ‘float *’ but argument is of type ‘float (*)[2]’
matmul89.c: In function ‘matrix_multiply’:
matmul89.c:17:29: warning: unused parameter ‘input_matrix1’ [-Wunused-parameter]
matmul89.c:17:51: warning: unused parameter ‘input_matrix2’ [-Wunused-parameter]
matmul89.c:17:70: warning: unused parameter ‘m’ [-Wunused-parameter]
matmul89.c:17:77: warning: unused parameter ‘p’ [-Wunused-parameter]
matmul89.c:17:84: warning: unused parameter ‘n’ [-Wunused-parameter]
matmul89.c:17:94: warning: unused parameter ‘output_matrix’ [-Wunused-parameter]
$
未使用的参数警告是合理的;该函数仍然是一个没有代码的虚拟函数。第 10 行是对 matrix_multiply()
的调用,不进行强制转换。正如您所看到的,GCC 诊断出矩阵参数的类型不是 float * 而是指针数组。第二个调用是我编写的方式,避免了任何强制转换的需要。第三个调用会迫使编译器接受带有强制类型转换的代码,实际上它会正常工作,但实际上没有必要这样做。
工作 C99 代码
如果您有可用的 C99,您可以利用 VLA(可变长度数组)来整齐地编写代码:
#include <stdio.h>
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(int m, int p, int n, float matrix1[m][p], float matrix2[p][n], float output[m][n]);
void matrix_print(const char *tag, int m, int n, float matrix[m][n]);
int main(void)
{
matrix_multiply(N, N, 1, m1, m2, result);
matrix_print("m1", N, N, m1);
matrix_print("m2", N, 1, m2);
matrix_print("m3", 1, N, result);
}
void matrix_multiply(int m, int p, int n, float matrix1[m][p], float matrix2[p][n], float output[m][n])
{
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
output[i][j] = 0.0;
for (int i = 0; i < m; i++)
for (int j = 0; j < p; j++)
for (int k = 0; k < n; k++)
output[i][k] += matrix1[i][j] * matrix2[j][k];
}
void matrix_print(const char *tag, int m, int n, float matrix[m][n])
{
printf("%s (%d x %d):\n", tag, m, n);
for (int i = 0; i < m; i++)
{
char *pad = "[";
for (int j = 0; j < n; j++)
{
printf("%s%6.3f", pad, matrix[i][j]);
pad = ", ";
}
printf("%s", " ]\n");
}
}
编译时不会出现警告,并产生看似合理的输出:
m1 (2 x 2):
[ 1.000, -0.020 ]
[ 0.000, 1.000 ]
m2 (2 x 1):
[ 1.500 ]
[ 1.500 ]
m3 (1 x 2):
[ 1.470, 1.500 ]
使用 C89 编写代码来模拟地址运算非常繁琐 — 并非不可能,但却很繁琐。
<小时/>工作 C89 代码
#include <stdio.h>
#define N 2
static float m1[N][N] = {{1.0, -0.02}, {0.0, 1.0}};
static float m2[N][1] = {{1.5f}, {1.5f}};
static float result[1][N];
void matrix_multiply(float *matrix1, float *matrix2, int m, int p, int n, float *output);
void matrix_print(const char *tag, int m, int n, float *matrix);
int main(void)
{
matrix_multiply(&m1[0][0], &m2[0][0], N, N, 1, &result[0][0]);
matrix_print("m1", N, N, &m1[0][0]);
matrix_print("m2", N, 1, &m2[0][0]);
matrix_print("m3", 1, N, &result[0][0]);
return 0;
}
/*
** Matrix Multiplication Routine
** matrix1 = input matrix (m x p)
** matrix2 = input matrix (p x n)
** m = number of rows in matrix1
** p = number of columns in matrix1 and number of rows in matrix2
** n = number of columns in matrix2
** output = output matrix = matrix1 * matrix2 (m x n)
*/
void matrix_multiply(float *matrix1, float *matrix2, int m, int p, int n, float *output)
{
int i, j, k;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
output[i*n+j] = 0.0;
for (i = 0; i < m; i++)
for (j = 0; j < p; j++)
for (k = 0; k < n; k++)
output[i*n+k] += matrix1[i*p+j] * matrix2[j*n+k];
}
void matrix_print(const char *tag, int m, int n, float *matrix)
{
int i, j;
printf("%s (%d x %d):\n", tag, m, n);
for (i = 0; i < m; i++)
{
char *pad = "[";
for (j = 0; j < n; j++)
{
printf("%s%6.3f", pad, matrix[i*n+j]);
pad = ", ";
}
printf("%s", " ]\n");
}
}
C89 和 C99 代码的输出是相同的。
关于C 编程调用函数...将 (float*)X 传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17192011/