Является ли следующий 2D-массив? - PullRequest
0 голосов
/ 27 сентября 2018

Я хотел динамически выделить 2D-массив с помощью указателей.

int *arr = (int *)malloc(rows * cols * sizeof(int));

это работает, но является ли этот массив с одним указателем технически двумерным массивом?

Спасибо!

Ответы [ 4 ]

0 голосов
/ 28 сентября 2018

Является ли следующий двумерный массив?

int *arr = (int *)malloc(rows * cols * sizeof(int));

Нет.arr это указатель.Этот указатель инициализируется с адресом памяти, подходящим для хранения 2D-массива.


Я хотел динамически распределить 2D-массив с помощью указателей.

Itзависит от вида "2D"

Идея "2D массива" часто используется свободно.Давайте рассмотрим некоторые возможные интерпретации.

Чтобы выделить указатель на двумерный массив, используйте следующее.Если rows,cols являются константами или код C99 или C11 с массивами переменной длины :

int (*arr_true)[rows][cols] = malloc(sizeof *arr_true);
(*arr_true)[0][0] = this;
(*arr_true)[0][1] = that;
// etc.

Чтобы выделить память для 2D-массива с шириной cols.Если cols является константой или код C99 или C11 с массивами переменной длины :

int *arr_mem[cols] = malloc(sizeof *arr_mem * rows);
arr_mem[0][0] = this;
arr_mem[0][1] = that;
// etc.

Чтобы выделить память для массива с row*cols элементами.

int *arr_flat = malloc(sizeof *arr_flat *rows * cols);
arr_flat[0 *cols + 0] = this;
arr_flat[0 *cols + 1] = that;
// etc.

Чтобы выделить массив указателей для указателей int

int *arr_classic = malloc(sizeof *arr_classic *rows);
for (size_t r = 0; r<rows; r++) {
  arr_classic[r] = malloc(sizeof *arr_classic[r] *cols);
}
arr_classic[0][0] = this;
arr_classic[0][1] = this;
// etc.

Идея улучшения для расчета размера.

Рассмотрим используемую математикурассчитать размер.Если бы rows,cols было int, rows * cols могло бы переполнить диапазон int, что привело бы к неопределенному поведению .Этот же расчет, выполненный с size_t, не может быть математически переполнен и должен быть предпочтительным.

В итоге malloc(size_t sz) ожидает size_t,

int *arrA = malloc(rows * cols * sizeof(int)); // possible int*int overflow
int *arrB = malloc(sizeof(int) * rows * cols); // preferred
0 голосов
/ 27 сентября 2018

Технически это просто одномерный массив.Но его можно использовать в качестве двумерного массива путем вычисления индексов на основе упорядочения основных строк:

int index = row * cols + col;
int val = arr[index];

Это то, что происходит за кулисами при объявлении двумерного массива:

int arr[rows][cols]
int val = arr[row][col];
0 голосов
/ 27 сентября 2018

Нет, указатель никогда массив.См. Раздел 6 comp.lang.c FAQ .

. Вы можете использовать эту технику для выделения порции памяти, которую затем можете обрабатывать как двумерный массив с указателем.arr указывает на его начальный элемент.Более простой и лучший способ написать это:

int *arr = malloc(rows * cols * sizeof (*arr));

Это выделяет одномерный массив из rows*cols int элементов.Вы не можете использовать нотацию arr[i][j] для индексации;вам нужно вычислить индекс самостоятельно: arr[i * rows + j].

Если вы хотите выделить динамический 2-мерный массив (или, точнее, структуру данных, которая действует как единое целое),вам нужно создать массив из int** указателей и инициализировать каждый элемент, чтобы он указывал на вновь выделенный массив из int элементов.(А затем вам нужно все вычистить, когда вы закончите.) Например:

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

int main(void) {
    int cols = 20;
    int rows = 10;

    // Allocate memory for an array of pointers to rows
    int **arr_2d = malloc(rows * sizeof *arr_2d);
    if (arr_2d == NULL) {
        abort(); // horribly crude error handling
    }

    // Allocate memory for each row
    for (int row = 0; row < rows; row ++) {
        int *arr_1d = malloc(cols * sizeof *arr_1d);
        if (arr_1d == NULL) {
            abort(); // horribly crude error handling
        }
        arr_2d[row] = arr_1d;
    }

    // Assign data 
    for (int row = 0; row < rows; row ++) {
        for (int col = 0; col < cols; col ++) {
            arr_2d[row][col] = row*col;
        }
    }

    // Dump data
    for (int row = 0; row < rows; row ++) {
        printf("Row %2d:", row);
        for (int col = 0; col < cols; col ++) {
            printf(" %3d", arr_2d[row][col]);
        }
        putchar('\n');
    }

    // Deallocate each row
    for (int row = 0; row < rows; row ++) {
        free(arr_2d[row]);
    }

    // Deallocate the array of row pointers
    free(arr_2d);
}
0 голосов
/ 27 сентября 2018
int *arr = (int *)malloc(rows * cols * sizeof(int));

arr - указатель на область памяти с rows * cols * sizeof(int) выделенными байтами.
Для языка не имеет значения, как вы интерпретируете область памяти, так как это зависит от вас.1D-массив, 2D-массив, строка и т. Д. В семантике C это, вероятно, будет 1D-массив, но это еще не вся правда, так как вы можете интерпретировать и управлять памятью так, как считаете нужным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...