C-将元素数组转换为二维矩阵

时间:2019-01-21 02:11:09

标签: c arrays

这可能是一个愚蠢的问题,但我想知道是否有一种有效的方法来做到这一点。

情况:

int* array = malloc(n * m * sizeof(int));
//want to convert array into M[n][m]

我现在正在做什么:

int** M = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++, array += m)
  M[i] = array; 

我认为转换不应该这么复杂。是否提供任何简单的语法C?我可以声明一个extern M[n][m]然后将其地址设置为数组吗?

(为简单起见,示例中省略了错误处理和内存管理。请将其视为某些功能的一部分。)

4 个答案:

答案 0 :(得分:2)

之后:

int* array = malloc(n * m * sizeof(int));

您可以这样做:

int (*M)[m] = (int(*)[m])array;

,然后使用M[1][2]为例。

您也可以首先这样做:

int (*M)[m] = malloc( n * sizeof *M );

答案 1 :(得分:1)

使用一个指针数组。

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

int main() 
{ 
    int n = 3, m = 4, i, j, count=0;

    int *array[n];
    for(i=0; i<n; i++)
     array[i] = (int *)malloc(m * sizeof(int));
     if( array[i] == NULL)
     {
        perror("Unable to allocate array");
        exit(1);
     }

    // going to add number to your 2d array.

    for (i = 0; i < n; i++)
      for (j = 0; j < m; j++)
         array[i][j] = ++count;

    for (i=0; i < n; i++)
      for (j=0; j < m; j++)
         printf("%d ", array[i][j]);

      // free memory

      for(i=0; i<n; i++)
         free(array[i]);

     }

答案 2 :(得分:1)

如果不给全局数组指定特定的数字大小,则不能在C中声明全局数组。这是因为全局变量是静态的,并且编译器无法为全局数组分配可变数量的内存。

在C语言中,您必须记住,数组实际上只是一个指针。当您询问int *array = malloc(n * sizeof(int))时,您告诉编译器的是您需要n并排保留的很多4类型的int类型的4字节块,其中{{1}的值}实际上是指向第一个4字节块的指针。

访问数组的元素时,实际上是在进行指针算术并取消对指针的引用,但这在array语法中是隐藏的。因此,当数组具有int类型时,array[i]随即转换为数组指针给定的位置(即头部),现在在内存中移动2 * 4字节,并取消引用指针以访问存储在那里的整数。

因此,正如您所讨论的,当您创建二维数组时,确实没有更好的方法。确保牢牢掌握从编译器获得的实际结果。指针(无论如何在64位计算机上)为8个字节,整数为4个字节。因此,当您调用array[2]时,编译器会为您分配m个宽度为8字节的块,所有块的类型均为int *。

从其他编程语言来看,似乎很重要的一点是必须声明对一个指针块的指针引用,但是通过更高级别的数组概念并将其视为指针的集合,从长远来看确实可以为您提供帮助跑。当您需要在函数之间传递这些数据类型时,您需要能够对自己实际操作的内容有一个清晰的认识。指针,值,指向指针的指针?这将极大地帮助您调试这些想法的代码,因为尝试对指针(而不是值)进行计算非常容易。

3条有用的提示:

  • int **M = malloc(sizeof(int*) * m比调用malloc更合适,因为calloc会自动将您的条目初始化为零,而malloc则不会。
  • 在调用calloc / malloc时,您要检查动态内存分配是否已成功;如果不成功,则malloc将返回NULL。
  • 一个好的经验法则是,每次调用malloc时,一旦完成内存操作,就想免费调用。这可以帮助防止内存泄漏。

答案 3 :(得分:1)

棘手的部分是声明变量以保存指向已分配数组的指针;其余的很简单-假设您使用的是C99或更高版本的编译器。

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

static void print_2dvla(int rows, int cols, int data[rows][cols])
{
    for (int i = 0; i < rows; i++)
    {
        printf("%2d: ", i);
        for (int j = 0; j < cols; j++)
            printf(" %4d", data[i][j]);
        putchar('\n');
    }
}

int main(void)
{
    int m = 10;
    int n = 12;

    int (*M)[m] = malloc(n * m * sizeof(M[0][0]));
    if (M == NULL)
    {
        fprintf(stderr, "Failed to allocate %zu bytes memory\n", n * m * sizeof(M[0][0]));
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
            M[i][j] = (i + 1) * 100 + (j + 1);
    }

    print_2dvla(n, m, M);

    free(M);
    return 0;
}

示例输出:

 0:   101  102  103  104  105  106  107  108  109  110
 1:   201  202  203  204  205  206  207  208  209  210
 2:   301  302  303  304  305  306  307  308  309  310
 3:   401  402  403  404  405  406  407  408  409  410
 4:   501  502  503  504  505  506  507  508  509  510
 5:   601  602  603  604  605  606  607  608  609  610
 6:   701  702  703  704  705  706  707  708  709  710
 7:   801  802  803  804  805  806  807  808  809  810
 8:   901  902  903  904  905  906  907  908  909  910
 9:  1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
10:  1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
11:  1201 1202 1203 1204 1205 1206 1207 1208 1209 1210

关键行是:

int (*M)[m] = malloc(n * m * sizeof(M[0][0]));

这表示M是指向int数组的指针,每个数组的维度为m。其余代码仅使用具有通常的2下标表示法的数组– M[i][j]等。可以将其传递给函数。我在这里没有显示它,但是将初始化代码也放入一个函数中,然后在一个函数中具有几个不同大小的矩阵,这很简单。