繁体   English   中英

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

[英]C - Convert array of elements into 2-d matrix

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

情况:

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]然后将其地址设置为数组吗?

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

后:

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

你可以做:

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

然后使用M[1][2]

您也可以首先这样做:

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

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

在C语言中,您必须记住,数组实际上只是一个指针。 当您要求int *array = malloc(n * sizeof(int)) ,您告诉编译器的是,您需要n个并排保留在内存中的int类型的4个字节的块,其中array实际上是指向前4个字节块的指针。

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

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

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

3个有用的技巧:

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

棘手的部分是声明变量以保存指向已分配数组的指针。 其余的很简单-假设您使用的是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数组的指针,每个int数组的维数为m 其余代码仅使用具有通常的2下标符号— M[i][j]等的数组。可以将其传递给函数。 我在这里没有显示它,但是将初始化代码也放到一个函数中,然后在一个函数中具有几个不同大小的矩阵,这很简单。

使用指针数组。

#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]);

     }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM