在C语言中如何声明一个可变大小的数组?

4

嗯,我正在做矩阵乘法,需要制作一个 m x n 数组和一个 p x q 数组。但是,我不知道怎么做。

这是我的程序,在手动输入值时打印正确的输出:

#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
    /*
        Rows and columns for matrices.
    */
    int m , n; // rows and columns of the first matrix
    int p , q; // rows and columns of the second matrix

    /*
        1st matrix is a 2x3 matrix
    */
    m = 2;
    n = 3;

    /*
        2nd matrix is a 3x2 matrix
    */
    p = 3;
    q = 2;


    /*
        Create the matrices.
        Give them values.
    */
    int matrix1[m][n] = {
                            {2,3,4},
                            {5,6,7}
                        };
    int matrix2[p][q] = {
                            {1,7},
                            {3,9},
                            {5,11}
                        };

    /*
        Check if we can multiple the matrices.
        For matrix multiplication,
        the number of COLUMNS of FIRST matrix must be equal to
        the number of ROWS of SECOND matrix
    */
    if(n==p){
        /*
            Create a new matrix.
            The resulting matrix will have M rows and Q columns.
            That is, the matrix is a MxQ matrix.
        */
        int matrix3[2][2]; 

        /*
            We need three loops so we have 3 variables.
        */
        int i = 0; // iterates over matrix1 rows
        int j = 0; // iterates over matrix1 columns
        int k = 0; // iterates over matrix2 rows
        int l = 0; // iterates over matrix2 columns


        while(i < m){
            l = 0;
            while(l < q){
                int element = 0;
                while(j < n && k < p){
                    element += matrix1[i][j] * matrix2[k][l];
                    matrix3[i][l] = element;
                    j++;
                    k++;
                }
                printf("\t%d",element);
                l++;
                j = 0;
                k = 0;
            }
            printf("\n");
            i++;
        }

    }else{
        printf("Matrices can not be multiplied");
    }
}  

矩阵声明被标记为错误。我该如何解决?

你的编译器是否支持可变长度数组(VLA)?并检查你的错误。即使支持VLA,也不支持初始化程序。 - WhozCraig
@WhozCraig 什么? :-/ VLA 是指可变长度数组。我使用Dev-C++,它使用的是GCC V 4.71。 - An SO User
3
这段代码其实不需要使用可变长度数组(VLA)。矩阵可以设为固定大小。 - WhozCraig
@WhozCraig 是的,但是..我只需要向教练展示我可以针对任何给定的输入矩阵完成它 :) 在Java中很容易,你知道的 :) - An SO User
如果您正在为任何给定的输入执行此操作,最好有一种替代方法来填充这些数组,而不是静态初始化。但请确定原始错误消息。它到底说了什么(请更新问题以包括它)。正如我所描述的那样,很可能VLAs不支持初始化(假设您的编译器支持VLAs,可以通过宏进行测试)。 - WhozCraig
@LittleChild:因为在Java中,数组是堆分配的。 - Ed S.
3个回答

3
我该怎么解决?
首先,不要使用VLA。您不需要为此特定任务使用VLA。
至于实际问题是什么:可变长度数组无法初始化。您必须逐个赋值给它们的元素或使用一些批量“赋值”技术,如memcpy()。

嗨,Carbonic Acid。我已经弄清楚了。我不能使用VLA :( - An SO User
@LittleChild 嗯,我的意思是无论你能否这样做都没关系--你根本不需要它们。将数组声明为int mat[2][3],然后你就可以立即初始化它了。 - user529758
我知道如果我那样做的话,我是可以做到的。我也可以使用宏来实现这一点。但和手动输入数值一样 :) - An SO User
@L 你的真正问题是获取用户输入吗? - user529758
@LittleChild 我相信你有一个 XY - P0W

1

你是否可以使用C99

可变长度数组

这在C99中是100%有效的:

  int m = 2;
  int n = 3;

  int matrix1[m][n];

我不知道。在大学里,数据结构是用C语言教授的,所以我的知识仅限于编写基本程序所需的内容 :) - An SO User
C99是C语言的最后一个版本,它支持VLA。我认为你应该问@LittleChild。我更新了我的答案,并附上了C99描述的链接。 - Cacho Santa
3
“这在C99中是100%有效的” - 不,它并不是,无法初始化可变长度数组(VLA)。只有静态大小的数组可以被初始化。 - user529758
1
一旦您对真实世界大小的矩阵进行操作,就会出现堆栈溢出。可变长度数组不适合解决此问题。 - David Heffernan

1
"本地的可变长度数组是一种可选的语言结构,根据当前的C标准。您需要查看编译器文档,确定您使用的编译器是否支持可变长度数组。在C99之前,可变长度数组需要显式地分配到堆上并通过指针访问。对于矩阵问题,您有两个选择。第一种是分配具有足够存储空间的数组,并在需要读取或修改矩阵元素时计算正确的索引。例如:"
int* matrix_storage = malloc( sizeof( int ) * matrix_width * matrix_height );
// set row 0, column 1 to 0
matrix_storage[ ( 0 * matrix_width ) + ( 1 % matrix_width ) ] = 0; 

或者您可以为每行或每列分配指针数组:

int** rows = malloc( sizeof( (int*) ) * matrix_height );
for( int i = 0; i < matrix_height; ++i )
{
    rows[i] = malloc( sizeof(int) * matrix_width );
}
row[0][1] = 0; // set row 0, column 1 to 0

这个实现会浪费一些内存,无论你选择哪种实现方式,都要考虑使用函数和struct关键字来隐藏实现细节,以免影响实际对矩阵进行操作或读取的驱动程序代码。

一些注意事项:我已经使用了c99的for循环语法,对于旧编译器,int i变量需要在for循环之外声明。此外,请注意,如果可以在编译时确定矩阵大小(即不依赖用户输入),则不需要malloc的开销,可以硬编码数组大小。你所贴出的示例代码并不需要动态分配内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接