C 编程调用函数...将 (float*)X 传递给函数

标签 c function prototype

我的代码如下所示

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

#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/

相关文章:

javascript - JS : Is there a difference between class. 原型(prototype).构造函数和类.构造函数

c - 使用 realloc 进行动态内存分配

iphone - 我遇到内存泄漏,负责的框架是 strdup。谁能给我一些线索?

C++,作为模板参数传递的成员函数

function - 如何检查Azure Function是否仍在运行

javascript - 为什么扩展 native 对象是一种不好的做法?

javascript - 在Javascript构造函数中使用 'this'来访问属性

c - 为什么gcc生成 "leal -8240(%ebp), %eax; cmpl $1, %eax; ja XXX"而不是jmp指令?

c - 使用 fgets 和 fscanf 时 C 中的段错误

c - argc 和 argv 用于 main 以外的函数