如何用C语言中的一个函数操作不同大小的矩阵?

如何用C语言中的一个函数操作不同大小的矩阵?,c,arrays,pointers,matrix,C,Arrays,Pointers,Matrix,我有一个来自Mathlab的代码,所有的矩阵运算都是由几个符号完成的。通过将其转换为C,我面临一个问题,即对于每种大小的矩阵,我都必须创建一个特殊的函数。这是一个很大的代码,我不会把它全部放在这里,但会尝试解释它是如何工作的 我还有一个大循环,其中有很多矩阵运算。使用矩阵操作的函数应将矩阵作为收入,并将结果存储在临时矩阵中以备后续操作。事实上,我知道矩阵的大小,但我也想使函数尽可能通用。为了减少代码大小和节省时间 例如,2x4和4x4矩阵的矩阵换位操作: void A_matrix_transp

我有一个来自Mathlab的代码,所有的矩阵运算都是由几个符号完成的。通过将其转换为C,我面临一个问题,即对于每种大小的矩阵,我都必须创建一个特殊的函数。这是一个很大的代码,我不会把它全部放在这里,但会尝试解释它是如何工作的

我还有一个大循环,其中有很多矩阵运算。使用矩阵操作的函数应将矩阵作为收入,并将结果存储在临时矩阵中以备后续操作。事实上,我知道矩阵的大小,但我也想使函数尽可能通用。为了减少代码大小和节省时间

例如,2x4和4x4矩阵的矩阵换位操作:

void A_matrix_transposition (float transposed_matrix[4][2], float matrix[2][4], int rows_in_matrix, int columnes_in_matrix);
void B_matrix_transposition (float transposed_matrix[4][4], float matrix[4][4], int rows_in_matrix, int columnes_in_matrix);

int main() {

float transposed_matrix_A[4][2]; //temporary matrices
float transposed_matrix_B[4][4];

float input_matrix_A[2][4], input_matrix_B[4][4]; //input matrices with numbers

A_matrix_transposition (transposed_matrix_A, input_matrix_A, 2, 4);
B_matrix_transposition (transposed_matrix_B, input_matrix_B, 4, 4);
// after calling the functions i want to use temporary matrices again. How do I pass them to other functions if i dont know their size, in general?
}

void A_matrix_transposition (float transposed_matrix[4][2], float matrix[2][4], int rows_in_matrix, int columnes_in_matrix)
{ static int i,j;
        for(i = 0; i < rows_in_matrix; ++i) {
        for(j = 0; j < columnes_in_matrix; ++j)
        { transposed_matrix[j][i] = matrix[i][j];
        }
    }
}

void B_matrix_transposition (float transposed_matrix[4][4], float matrix[4][4], int rows_in_matrix, int columnes_in_matrix)
{ static int i,j;
        for(i = 0; i < rows_in_matrix; ++i) {
        for(j = 0; j < columnes_in_matrix; ++j)
        { transposed_matrix[j][i] = matrix[i][j];
        }
    }
}
void A_matrix_transposition(float transposed_matrix[4][2]、float matrix[2][4]、int rows_in_matrix、int columns_in_matrix);
无效B_矩阵_变换(浮点变换_矩阵[4][4],浮点矩阵[4][4],矩阵中的int行_,矩阵中的int列_);
int main(){
浮点转置_矩阵_A[4][2];//临时矩阵
浮点转置_矩阵_B[4][4];
浮点输入矩阵A[2][4],输入矩阵B[4][4];//带数字的输入矩阵
A_矩阵_变换(变换矩阵_A,输入矩阵_A,2,4);
B_矩阵_变换(变换矩阵_B,输入矩阵_B,4,4);
//调用函数后,我想再次使用临时矩阵。如果我不知道它们的大小,通常如何将它们传递给其他函数?
}
无效A_矩阵_转置(浮点转置_矩阵[4][2],浮点矩阵[2][4],矩阵中的int行_,矩阵中的int列_)
{静态int i,j;
对于(i=0;i<矩阵中的行数;++i){
对于(j=0;j<矩阵中的列;++j)
{转置_矩阵[j][i]=矩阵[i][j];
}
}
}
无效B_矩阵_变换(浮点变换_矩阵[4][4],浮点矩阵[4][4],矩阵中的int行_,矩阵中的int列_)
{静态int i,j;
对于(i=0;i<矩阵中的行数;++i){
对于(j=0;j<矩阵中的列;++j)
{转置_矩阵[j][i]=矩阵[i][j];
}
}
}
操作很简单,但是由于有两个不同的函数,代码已经很庞大了,但是如果我继续这样做的话,这将是一个缓慢的灾难

我如何创建一个函数进行转置以操作不同大小的矩阵

我想可以用指针来做,但我不知道怎么做


我正在寻找一个真实的一般的答案,以了解如何调整函数和临时矩阵之间的“通信”,最好用一个例子。提前感谢所有人提供的信息和帮助。

从不太好的解决方案到很好的解决方案,您可以通过不同的方式实现这一点

如果您知道矩阵的最大大小,您可以创建一个足够大的矩阵来容纳该大小,并对其进行处理。如果小于该值,则可以编写自定义操作,只考虑小的子矩阵,而不是整个子矩阵

另一种解决方案是创建一个数据结构来保存矩阵,这可能不同于使用存储在结构本身中的属性创建交错数组。例如:行数和列数信息将存储在结构本身中。锯齿数组的好处是,现在可以分配取消分配的内存,从而更好地控制矩阵的形式顺序。更好的是,现在你可以传递两个不同大小的矩阵,函数都可以看到包含实际矩阵的结构,并对其进行处理。(我会说)。 我所说的结构是指

struct matrix{
   int ** mat;
   int row;
   int col;
}

如果您的C实现支持可变长度数组,则可以通过以下方式实现:

void matrix_transposition(size_t M, size_t N,
    float Destination[M][N], const float Source[N][M])
{
    for (size_t m = 0; m < M; ++m)
    for (size_t n = 0; n < N; ++n)
        Destination[m][n] = Source[n][m];
}
(不幸的是,这会阻止编译器检查参数类型是否与预期类型匹配,但这是C的一个缺点。)

如果您需要一个严格使用标准C且没有可变长度数组的解决方案,那么从技术上讲,正确的方法是复制对象的字节:

void matrix_transposition(size_t M, size_t N,
    void *DestinationPointer, const void *SourcePointer)
{
    char *Destination = DestinationPointer;
    const char *Source = SourcePointer;

    for (size_t m = 0; m < M; ++m)
    for (size_t n = 0; n < N; ++n)
    {
        // Calculate locations of elements in memory.
        char *D = Destination + (m*N+n) * sizeof(float);
        const char *S = Source + (n*M+m) * sizeof(float);
        memcpy(D, S, sizeof(float));
    }
}
void matrix\u transposition(大小\u t M,大小\u t N,
void*DestinationPointer,const void*SourcePointer)
{
char*Destination=DestinationPointer;
const char*Source=SourcePointer;
用于(尺寸m=0;m
笔记: 包含
以声明
大小
,如果使用上一个解决方案,则包含
以声明
memcpy


可变长度数组在C 1999中是必需的,但在C 2011中是可选的。通用系统的高质量编译器将支持它们。

如果您使用的是C99编译器,则可以使用可变长度数组(VLA)(在C11编译器中是可选的)。您可以编写如下函数:

void matrix_transposition (int rows_in_matrix, int columnes_in_matrix, float transposed_matrix[columnes_in_matrix][rows_in_matrix], float matrix[rows_in_matrix][columnes_in_matrix])
{ 
    int i,j;
    for(i = 0; i < rows_in_matrix; ++i) {
        for(j = 0; j < columnes_in_matrix; ++j)
        { 
            transposed_matrix[j][i] = matrix[i][j];
        }
    }
}
matrix_transposition (2, 4, transposed_matrix_A, input_matrix_A);
matrix_transposition (4, 4, transposed_matrix_B, input_matrix_B);

您可能不想在程序中硬编码数组大小。我建议使用一个包含单个平面阵列的结构,然后可以在二维中对其进行解释:

typedef struct {
    size_t width;
    size_t height;
    float *elements;
} Matrix;
将其初始化为

int matrix_init(Matrix *m, size_t w, size_t h)
{
    m.elements = malloc((sizeof *m.elements) * w * h);
    if (!m.elements) {
        m.width = m.height = 0;
        return 0; /* failed */
    }
    m.width = w;
    m.height = h;
    return 1; /* success */
}
然后,为了找到位置(x,y)处的元素,我们可以使用一个简单的函数:

float *matrix_element(Matrix *m, size_t x, size_t y)
{
    /* optional: range checking here */
    return m.elements + x + m.width * y;
}
这比指针数组具有更好的局部性(并且更容易、更快地正确分配和取消分配),并且比数组数组更灵活(如您所发现的,内部数组需要编译时常量大小)


您可能能够使用一个包装在
矩阵
结构中的数组数组-如果数组数组在您的平台上有填充,您可能需要一个
跨步
,它不一定与
宽度
相同。

在C中正确的方法是创建一个
结构矩阵
,元素的2D数组指针和两个等于数字o的整数值
int matrix_init(Matrix *m, size_t w, size_t h)
{
    m.elements = malloc((sizeof *m.elements) * w * h);
    if (!m.elements) {
        m.width = m.height = 0;
        return 0; /* failed */
    }
    m.width = w;
    m.height = h;
    return 1; /* success */
}
float *matrix_element(Matrix *m, size_t x, size_t y)
{
    /* optional: range checking here */
    return m.elements + x + m.width * y;
}