Как мне выделить двумерный массив с постоянной памятью? Как использовать его для доступа к строкам и столбцам? Дайте мне пример

Я создал 2-мерный массив, который выглядит следующим образом

     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, как показано в моем коде


person srinivasavaradan    schedule 14.02.2010    source источник
comment
Что это? a [0] = (двойной *) malloc ((lx + 2) * (ly + 2) * sizeof (double)); Это не то, как вы инициализируете второе измерение массива.   -  person Dark Falcon    schedule 14.02.2010
comment
Я помечаю это c, поменяйте, если ошибаюсь. Этот сайт предназначен для всех программных мероприятий, большинство читателей здесь вообще не используют C. Помогите людям, которые могут помочь вам найти ваш вопрос, с помощью значимых тегов.   -  person Pascal Cuoq    schedule 14.02.2010
comment
Это подозрительно похоже на домашнее задание. Вы можете объяснить lx и ly? Похоже, они не инициализированы.   -  person John M. P. Knox    schedule 14.02.2010
comment
Привет, Джон! Это в значительной степени домашнее задание, но его часть. Мне нужно научиться работать с двумя смежными массивами, чтобы завершить все задание.   -  person srinivasavaradan    schedule 14.02.2010


Ответы (4)


Ваш подход определенно движется в правильном общем направлении.

Я думаю, что это:

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
person DigitalRoss    schedule 14.02.2010
comment
HI Использование двух malloc не даст мне непрерывной памяти, верно? Я ожидаю непрерывной памяти ... Следовательно, есть ли какой-либо механизм для этого? - person srinivasavaradan; 14.02.2010
comment
Верно, иногда ТАК вознаграждает за дополнительные ответы, извините за задержку. :-) Последняя строка работает, потому что i * lx сначала вычисляется, а затем становится pointer + int, что приводит к масштабированию int в соответствии с размером объекта. - person DigitalRoss; 14.02.2010
comment
Привет, второй код выглядит круто. Не могли бы вы подробнее рассказать? Это то, что я понимаю ... Я просто указываю [i] на каждую строку в массиве правильно? Теперь, что мне нужно сделать, чтобы получить доступ к тому же, чтобы заполнить значения как в строках, так и в столбцах. Заранее благодарим за быстрый ответ. - person srinivasavaradan; 14.02.2010
comment
И что будет, если я сделаю что-то подобное? a = (двойной *) malloc ((lx + 2) * (ly + 2) * sizeof (double)); для (i = 0; i ‹(lx + 2) * (ly + 2); i ++) {a [i] = 0; } - person srinivasavaradan; 14.02.2010
comment
Даже в моем последнем примере вам по-прежнему нужен первый malloc, который выделяет вектор указателей на исходные строки. Итак, вы затем обращаетесь к массиву с помощью a[i][j]. Так что, может быть for(i=0; i<lx; ++i) for (j=0; j<ly; ++j) a[i][j] = 0.0; - person DigitalRoss; 14.02.2010
comment
Спасибо, но разве * t не одномерный массив? Если это так, то как я могу использовать [i] [j]? Насколько я понимаю, мы можем использовать только one [] для одномерного массива и 2 [] [] для двумерного массива. - person srinivasavaradan; 14.02.2010
comment
Сначала да, t имеет одно измерение, но мы берем то место, где каждая строка начиналась бы, если бы t была объявлена ​​статически, и назначаем начало этой строки правому элементу вектора указателя a[]. Это не то же самое, что 2D-массив, это вектор указателя, но он используется таким же образом в более позднем исходном коде и может быть быстрее, поскольку компилятору не нужно умножать индекс строки на длину строки. Попробуйте пример, он работает. :-) - person DigitalRoss; 14.02.2010
comment
Привет, большое спасибо. Росс, как я могу связаться с вами, кроме переполнения стека? Могу я в первую очередь? и если я могу, то любезно дайте мне знать, как? Мой почтовый идентификатор [email protected] - person srinivasavaradan; 14.02.2010

Этот код выделяет непрерывный блок памяти размером 10 на 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 не будет работать.

person John M. P. Knox    schedule 14.02.2010

Либо вы создаете одномерный массив

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

к которому вы получите доступ

(получить позицию x = 28, y = 12)

my_array[12 * size_x + 28];

или вы создаете 2d-массив, как вы, но вы получаете к нему доступ с помощью

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];
person Eric    schedule 14.02.2010
comment
HI Использование двух malloc не даст мне непрерывной памяти, верно? Я ожидаю непрерывной памяти ... Следовательно, есть ли какой-либо механизм для этого? - person srinivasavaradan; 14.02.2010
comment
@srinivasavaradan, Первый ответ здесь дает вам непрерывную память. - person Carl Norum; 14.02.2010
comment
О, тогда я думаю, это должно быть double * my_array = malloc (sizeof (double) * size_x * sizeof (double) * size_y); // Я прав? - person srinivasavaradan; 14.02.2010
comment
вам не хватало * при объявлении my_array - person srinivasavaradan; 14.02.2010
comment
@srinivassavaradan, да, похоже, там отсутствует *. - person Carl Norum; 14.02.2010
comment
Первый пример очень ошибочен. Вы, вероятно, имеете в виду double *my_array вместо double my_array, но даже тогда вызов malloc() неверен. Вам нужен только один sizeof(double), а не два в sizeof операнде. - person Alok Singhal; 15.02.2010

В 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);

Использование sizeof с sizeof *pt вместо sizeof(T) дает то преимущество, что при изменении типа pt вам не нужно изменять вызов malloc(). Отсутствие преобразования результата malloc() - это хорошо, потому что тогда весь вызов malloc() не зависит от типа, и его легче набирать и читать. Но обязательно #include <stdlib.h>.

Итак, чтобы выделить место для n doubles, вы можете:

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

Теперь, после выделения памяти, вам нужно иметь возможность ее проиндексировать. Допустим, у вас есть lx == 2 и ly == 3. Ваша память выглядит так:

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

pd[0], pd[1] и pd[2] - значения double, соответствующие первой строке, от pd[3] до pd[6] - значения double, соответствующие второй строке. Вы должны быть в состоянии обобщить это наблюдение, чтобы преобразовать данную пару индексов x,y в одно число, которое правильно индексируется в массиве pd.

person Alok Singhal    schedule 15.02.2010