0

我有下面显示的以下代码

要调用该函数,代码类似于以下内容:

#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*)调用函数时使用的。谁能详细描述一下。

4

1 回答 1

1

符号(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]
$

未使用的参数警告是合理的;该函数仍然是一个没有代码的虚拟函数。matrix_multiply()第 10 行是没有强制转换的调用。如您所见,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 代码的输出是相同的。

于 2013-06-19T14:07:30.247 回答