如何分配具有连续内存的二维数组?如何使用它来访问行和列?给我一个例子

Posted

技术标签:

【中文标题】如何分配具有连续内存的二维数组?如何使用它来访问行和列?给我一个例子【英文标题】:How do I allocate a 2 D array with contigious memory ? How Do I use it to access rows and columns? Give me an example 【发布时间】:2011-01-16 14:47:30 【问题描述】:

我创建了一个二维数组,内容如下

     int i,j,lx,ly;// lx,ly are the row and column respectively
     double** a;

     a=(double**) malloc((lx+2)*sizeof(double));

     a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));

     assert(a[0]); 

     for(i=1;i<lx+2;i++)
     
       a[i]=a[i-1]+i*(ly+2);
     

//我为这个数组中的所有元素分配一个值0,如下所示

    for(i=0;i<(lx+2)*(ly+2);i++)
    
      a[i]=0;
     

// 我打印出下面的所有元素

      for(i=0;i<(lx+2)*(ly+2);i++)
      
         printf("position %d values %d\n",i,a[i]);
       

// 当我看到输出时,它在一个特定位置 13 处显示了一个垃圾值。我无法弄清楚.. 还请告诉我如何访问行和列,例如 Eg 以访问第 7 列行0 和第 5 行第 6 列以 lx 表示,ly 如我的代码所示

【问题讨论】:

这是什么? a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));这不是初始化数组第二维的方式。 我标记了这个c,如果我错了就改。该站点适用于所有编程活动,大多数读者在这里根本不使用 C。使用有意义的标签帮助可以帮助您找到问题的人。 这看起来有点像家庭作业。你能解释一下lx和ly吗?它们似乎没有被初始化。 嗨,约翰,这是一个非常重要的家庭作业,但也是其中的一部分。我需要学习如何使用连续的二维数组来完成整个任务。 【参考方案1】:

在 C 中,要拥有一块连续的内存,您需要一个 malloc(),或者拥有一个静态分配的数组。由于您需要动态内存,因此您需要malloc()。由于您需要所有内容都是连续的,因此您只需要 一个 调用它。

现在,调用应该是什么样的?如果我理解正确,您需要lx 乘以ly 值,每个值的大小为sizeof(double),因此您需要分配lx*ly*sizeof(double) 字节。

题外话:我更喜欢这样写我的malloc() 调用:

#include <stdlib.h> /* for malloc's prototype */
T *pt; /* for any type T */
size_t n; /* need n objects of type T */

pt = malloc(n * sizeof *pt);

sizeofsizeof *pt 一起使用而不是sizeof(T) 的优势在于,如果pt 的类型发生变化,您无需更改malloc() 调用。不转换malloc() 的结果很好,因为整个malloc() 调用与类型无关,并且更易于键入和阅读。不过请务必#include &lt;stdlib.h&gt;

所以,要为ndoubles 分配空间,你可以这样做:

double *pd = malloc(n * sizeof *pd);
if (pd != NULL) 
    /* malloc succeeded */
 else 
    /* malloc failed */

现在,在分配内存之后,您需要能够对其进行索引。假设您有lx == 2ly == 3。你的记忆是这样的:

    +---+---+---+---+---+---+
pd: | 0 | 1 | 2 | 3 | 4 | 5 |
    +---+---+---+---+---+---+

pd[0]pd[1]pd[2]是第一行对应的double值,pd[3]pd[6]是第二行对应的double值。您应该能够概括此观察结果,将给定的x,y 索引对转换为正确索引到您的pd 数组中的一个数字。

【讨论】:

【参考方案2】:

此代码分配一个 10 x 5 的连续内存块,用递增的双精度数对其进行初始化,然后打印由 x 和 y 索引的值:

#include "2d.h"

int main(void)

    unsigned int x,y;
    const unsigned int width = 10;
    const unsigned int height = 5;

    //we need an index into the x of the array
    double * index[width];

    //need the memory to store the doubles
    unsigned int memorySizeInDoubles = width * height;
    double * memory = malloc(memorySizeInDoubles * sizeof(double));

    //initialize the memory with incrementing values
    for(x = 0; x < memorySizeInDoubles; ++x)
        memory[x] = (double) x;
    

    //initialize the index into the memory
    for(x = 0; x < width; ++x)
        index[x] = memory + height * x;
    

    //print out how we did
    for(x = 0; x < width; ++x)
        for(y = 0; y < height; ++y)
           printf("[%u, %u]: Value = %f\n", x, y, index[x][y]);
        
    

    free(memory);

    return 0;

2d.h 文件应包含以下行:

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

int main(void);

注意:创建的内存仅对某些定义是连续的。内存在逻辑上是连续的,但不一定在物理上是连续的。例如,如果此内存用于设备驱动程序,则 malloc 将不起作用。

【讨论】:

【参考方案3】:

您的方法肯定朝着正确的大方向前进。

我认为是这样的:

a=(double**) malloc((lx+2)*sizeof(double));

通常是:

a = malloc(lx * sizeof(double *));

然后没有连续性要求,这个:

a[0]= (double*) malloc((lx+2)*(ly+2)* sizeof(double));

在大多数程序中看起来像:

a[0] = malloc(ly * sizeof(double));

最后,最后一行需要在一个循环中,为每个 a[i] 分配它自己的 malloc'ed 空间。

但是,这不会创建连续的内存。为此,您需要进行大分配,然后将其划分为行向量。因此,而不是循环中的第二个 malloc,可能类似于:

double *t = malloc(lx * ly * sizeof(double));
for (i = 0; i < lx; ++i)
    a[i] = t + i * ly;

把它们放在一起:

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

void arrayDemo(int lx, int ly)

  double **a;
  int i, j;

  a = malloc(lx * sizeof(double *));
  double *t = malloc(lx * ly * sizeof(double));
  for(i = 0; i < lx; ++i)
    a[i] = t + i * ly;

  for(i = 0; i < lx; ++i)
    for(j = 0; j < ly; ++j)
      a[i][j] = i*100 + j;
  for(i = 0; i < lx; ++i) 
    for(j = 0; j < ly; ++j)
      printf(" %4.0f", a[i][j]);
    printf("\n");
  


int main(int ac, char **av)

  arrayDemo(atoi(av[1]), atoi(av[2]));
  return 0;


$ cc -Wall all.c
$ ./a.out 4 7
    0    1    2    3    4    5    6
  100  101  102  103  104  105  106
  200  201  202  203  204  205  206
  300  301  302  303  304  305  306

【讨论】:

HI 使用 2 个 malloc 不会给我一个连续的记忆,对吧?我期待的是一个连续的记忆......因此有没有什么机制可以做到这一点? 是的,有时 SO 会奖励增量答案,抱歉耽搁了。 :-) 最后一行有效,因为首先评估 i * lx 然后变为 pointer + int 导致 int 按对象大小缩放。 嗨,第二个代码看起来很酷。你能详细说明一下吗?这就是我所理解的......我只是让 [i] 指向数组中的每一行正确吗?现在我需要做什么来访问相同的,以填充行和列中的值。提前感谢您的快速回复。 如果我这样做会发生什么? a=(double*) malloc((lx+2)*(ly+2)*sizeof(double)); for(i=0;i 即使在我的最后一个示例中,您仍然需要第一个 malloc,它分配指向原始行的指针向量。因此,您可以使用a[i][j] 访问该数组。所以也许for(i=0; i&lt;lx; ++i) for (j=0; j&lt;ly; ++j) a[i][j] = 0.0;【参考方案4】:

要么你创建一个单维数组

double my_array = malloc(sizeof(double) * size_x * sizeof(double) * size_y);

你将通过它访问

(获取位置 x=28, y=12)

my_array[12 * size_x + 28];

或者你像你一样创建一个二维数组,但是你使用

double **my_array = (double**) malloc(15 * sizeof(double));

for(int i = 0 ; i < 25; i++)
   
   my_array[i] = (double*) malloc(30 * sizeof(double));
   for (int j = 0 ; j < 12; j++)
      
      my_array[i][j] = 1.2;
      
   

double my_double = my_array[12][28];

【讨论】:

HI 使用 2 个 malloc 不会给我一个连续的记忆,对吧?我期待的是一个连续的记忆......因此有什么机制可以做到这一点? @srinivasavaradan,这里的第一个答案给你连续的记忆。 哦,那我猜应该是 double * my_array = malloc(sizeof(double) * size_x * sizeof(double) * size_y); // 我说的对吗? 在声明 my_array 时是否遗漏了 * @srinivassavaradan,是的,那里似乎缺少*

以上是关于如何分配具有连续内存的二维数组?如何使用它来访问行和列?给我一个例子的主要内容,如果未能解决你的问题,请参考以下文章

c语言问题:c语言中二维数组在内存中怎样存储?

c++中二维数组的内存分配

C#/Java 如何存储二维数组,与 C++ 不同?

指向动态二维字符数组的三重指针的内存分配

C语言动态分配二维字符串数组

如何创建二维数组