Вызов двумерного массива

Чтобы сделать двумерный массив, я сейчас использую следующее:

int * own;

own = (int *)calloc(mem_size, sizeof(int));

for (i=0;i<mem_size;i++){
    own[i] = (int *)calloc(3, sizeof(int));
}

Однако каждый раз, когда я ссылаюсь на own[i][j], я получаю сообщение об ошибке, говорящее о том, что значение с индексом не является ни массивом, ни указателем, ни вектором.


person db2791    schedule 30.04.2015    source источник
comment
own должно быть int**.   -  person Daniel Kamil Kozar    schedule 30.04.2015
comment
Часто лучше смоделировать двумерный массив как непрерывный блок и использовать i x rows + j для доступа к элементам. Рассмотрите это как альтернативу.   -  person Bathsheba    schedule 30.04.2015
comment
Если быть точнее, то это не 2D-массив, а всего лишь эмуляция такой штуки через указатели на указатели. Не делай этого, если не должен. int (*own)[n] = malloc(sizeof(int[m][n])); — это все, что вам нужно для приличного компилятора C.   -  person Jens Gustedt    schedule 01.05.2015
comment
@JensGustedt: вы должны ответить на этот вопрос - это ни в коем случае не очевидная техника. На самом деле, я не думаю, что когда-либо видел его раньше. (если у вас есть время и желание, было бы неплохо рассказать о том, что представляет собой достойный или неадекватный компилятор).   -  person Michael Burr    schedule 01.05.2015
comment
@MichaelBurr, здесь это не подходит в качестве ответа, вопрос более конкретен. И я также делал это несколько раз, писал об этом в блоге, ..., просто распространял информацию. gustedt.wordpress.com/2011 /01/09/   -  person Jens Gustedt    schedule 01.05.2015


Ответы (5)


Использовать:

int ** own; // int**, not int*
own = calloc(mem_size, sizeof(int*)); //int*, not int
                                      // And remove the explicit cast.
person R Sahu    schedule 30.04.2015

Однако каждый раз, когда я ссылаюсь на own[i][j], я получаю сообщение об ошибке, говорящее о том, что значение с индексом не является ни массивом, ни указателем, ни вектором.

Это верно. own[i] эквивалентно *(own + i), имеющему тип int. Вы не можете применить оператор нижнего индекса к int.

Обратите внимание, что ваш код пытается создать не двумерный массив, а скорее массив указателей. Если это действительно то, что вам нужно, то own должен иметь тип int **, и вы должны соответствующим образом настроить первый вызов calloc(). Если вам действительно нужно динамическое выделение 2D-массива, то это будет:

int (*own)[3];

own = calloc(mem_size, sizeof(*own));

Обратите внимание, что тогда нет необходимости выделять (или освобождать) строки отдельно.

Однако обратите внимание, что если вам никогда не нужно перераспределять own до того, как он выйдет за рамки, если вы можете предположить, по крайней мере, компилятор C99, и если mem_size никогда не будет слишком большим, вы можете сделать это еще проще через массив переменной длины:

int own[mem_size][3] = {{0}};

В этом случае вообще не требуется явного динамического выделения или освобождения, а инициализатор можно опустить, если он не нужен. (Я включаю инициализатор, потому что calloc() выполняет эквивалентную инициализацию выделенного пространства.) «Слишком большой» следует интерпретировать по отношению к массиву, выделенному в стеке.

person John Bollinger    schedule 30.04.2015
comment
Стандартное предупреждение о том, что VLA размещены в стеке, поэтому VLA может быть не очень хорошей идеей, если mem_size — большое число. - person user3386109; 30.04.2015
comment
@ user3386109, спасибо, я обновил свой ответ, включив в него предупреждение о распределении стека для VLA. - person John Bollinger; 30.04.2015

Поскольку own объявлен как имеющий тип int *

int * own;

тогда own[i] является скалярным объектом типа int и вы не можете применять к нему оператор нижнего индекса.

Вы можете написать следующим образом

int ( *own )[3] = calloc( mem_size, 3 * sizeof( int ) );

Другой способ следующий

int **own = malloc( mem_size * sizeof( int * ) );

for ( i = 0; i < mem_size; i++ ) own[i] = calloc( 3, sizeof( int ) );
person Vlad from Moscow    schedule 30.04.2015

Неправильный тип для двумерного массива - многие хорошо указывали.

Другое предлагаемое решение.

При распределении используйте sizeof переменную, а не sizeof тип. Меньше шансов ошибиться - легче поддерживать.

//int * own;
int **own;

own = calloc(row_count, sizeof *own);
for (i=0; i<row_count; i++){
  own[i] = calloc(column_count, sizeof *(own[i]));
}
person chux - Reinstate Monica    schedule 30.04.2015

int *own = calloc(100, sizeof(int));

Для построения массива 2D-массив в памяти выглядит следующим образом => введите здесь описание изображения

Таким образом, к нему можно получить доступ с помощью такой формулы

*(own + rows*y +x)

Использование этого типа массива очень простое и открытое, например, когда у нас есть 100 ячеек памяти и мы можем сделать из них массив размером 100 кратных.
Например, в 100 домах массив этого можно указать размер =›
[1][100]= (собственный + 1y +x)
[2][50]= (собственный + 2 y +x)
[4][25]= (собственный + 4y +x)
[5][20]= (собственный + 5y +x)
[10][10] = (свои + 10y +x)
Извините, если я был не прав, потому что я говорю по-персидски и я плохо знаю английский


Пример:

int *aPtr = calloc(100, sizeof(int));
for(int y=0;y<4;y++){
    for(int x=0;x<25;x++){
        *(own + 25*y +x) = 1;
    }
}
person ali naderi    schedule 05.03.2021