Инициализация двумерного массива без указания размера

Я могу инициализировать одномерный массив в c с инициализацией или без инициализации его размера:

int x[] = {1,2,3,4,5};
int y[5] = {1,2,3,4,5};

Но когда я пытаюсь сделать то же самое для двумерного массива, такого как

int x[][] = {{1,2,3},
             {4,5,6}};

Я получаю error: array type has incomplete element type. Та же ошибка возникает, если я объявляю и инициализирую массив в разных строках. Однако я могу инициализировать его, указав размер:

int x[2][3] = {{1,2,3},
               {4,5,6}};

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


person Daniel    schedule 23.09.2017    source источник
comment
Если он имеет динамический размер, как вы предоставите список инициализаторов в коде?   -  person Barmar    schedule 23.09.2017
comment
Что вы подразумеваете под объявлением и инициализацией массива в разных строках? Единственный способ инициализировать массив — это объявление.   -  person Barmar    schedule 23.09.2017
comment
@Barmar, мой плохой, я думаю, я хотел сказать, определить. Как и в случае с int x[][]; а затем в другом месте введите x[][] =...   -  person Daniel    schedule 23.09.2017
comment
@Barmar Что касается динамических размеров, то с моей стороны это была плохая формулировка. Я имею в виду, что размер массива не будет известен при компиляции.   -  person Daniel    schedule 23.09.2017
comment
Чтобы расширить то, что написал @barmer: вы можете инициализировать переменную только с объявлением. Что делает это определением (не единственным способом определения, но окончательно). И если размер неизвестен во время компиляции, вы не можете инициализировать его во время компиляции (мне это кажется разумным). Может быть, вы хотите провести небольшое исследование в своей книге C об объявлении, определении и инициализации.   -  person too honest for this site    schedule 23.09.2017
comment
Узнайте о VLA, доступных начиная с C99 (но ставших необязательными в C11; по-прежнему широко доступны).   -  person ad absurdum    schedule 23.09.2017
comment
Если вы знаете список значений для инициализации, как в вашей попытке int[x][y] инициализации, то как вы можете не знать размер? Оставить размер пустым — это просто удобство в первой строке кода — компилятор подсчитывает инициализаторы вместо того, чтобы заставлять вас это делать. Но это все еще известно во время компиляции.   -  person Barmar    schedule 24.09.2017
comment
Если вы не знаете размер и начальные значения до времени выполнения, то вы, очевидно, не можете инициализировать его такими литералами. Используйте либо VLA, либо динамическое размещение с malloc().   -  person Barmar    schedule 24.09.2017
comment
@Comrade_Comski Независимо от того, как вы это объявите, вы никогда не можете назначать массив, вы можете назначать только отдельные элементы.   -  person Barmar    schedule 24.09.2017


Ответы (3)


можно ли инициализировать многомерный массив без предварительной инициализации его размера?

Нет, не так, как вы предлагаете, или что-то подобное.

Мне нужно иметь возможность объявлять массивы и инициализировать их позже, и они будут иметь динамические размеры.

Если размер неизвестен во время компиляции, вы должны выделить массив, используя a = malloc(x * y * sizeof(value_t)). Затем индексируйте его, например a[i + j*y].

person John Zwinck    schedule 23.09.2017
comment
Разве массивы переменной длины тоже не возможны? - person Barmar; 23.09.2017
comment
Обратите внимание, что вы должны проверять умножение x*y*sizeof(value_t) на целочисленные переполнения. - person ndim; 23.09.2017
comment
VLA не требует динамического распределения. Если вы хотите использовать его, вы все равно можете использовать VLA. Использование одномерного массива и ручное вычисление индекса не является двумерным массивом, подверженным ошибкам и устаревшим с 18 лет. - person too honest for this site; 23.09.2017

Is it possible to initialize a multi dimensional array without first initializing its size?

=> Нет, это невозможно.

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

Теперь использование calloc будет применяться как:

Предполагая, что вам нужен 2D-массив, вы принимаете переменные row и column в качестве входных данных от пользователя. Затем используйте,

int *x;
x = calloc( ( row * column), sizeof(datatype) );

В этом случае тип данных будет int.

В кратком коде будет выглядеть так:

int row, column, *x;

    /* TAKING INPUT FROM THE USER */
printf("\n\t Enter the number of rows : ");
scanf("%d", &row);
printf("\n\t Enter the number of columns : ");
scanf("%d", &column);

    /* DYNAMICALLY ALLOCATING MEMORY TO x USING calloc */
x = calloc( (row * column), sizeof(int));

Я надеюсь, что этот код решит вашу проблему.

У меня есть еще одна вещь, чтобы поделиться с вами.

В вашей этой строке кода:

int x[][] = {{1,2,3},
             {4,5,6}};

В этой инициализации просто отсутствует одна вещь, а именно упоминание о размере столбца, а в остальном код правильный.

Итак, исправление вашего кода:

int x[][3] = {{1,2,3},
             {4,5,6}};

Это будет работать нормально.

Продолжать пытаться! Такие вещи можно узнать только во время практики.

Удачного кодирования!

person Jorvis    schedule 24.09.2017

Да, но вы пропустили запятую:

int x[2][3] = {{1,2,3},
               {4,5,6}};

Все элементы массива (даже внутренние массивы) должны быть разделены запятыми.

person ACVM    schedule 23.09.2017
comment
Не вызовет ли это синтаксическую ошибку, если массив не имеет неполного типа? - person Barmar; 23.09.2017
comment
Все, что я знаю, это то, что у него синтаксическая ошибка... массив с одним значением">stackoverflow.com/questions/15520880/ - person ACVM; 23.09.2017
comment
У него также есть эта синтаксическая ошибка в версии, которая, по его словам, работает. Я думаю, что он просто неправильно скопировал это в вопрос. - person Barmar; 23.09.2017
comment
Его вопрос заключался в том, как это сделать, не добавляя [2][3] в размер. - person Barmar; 23.09.2017
comment
Ах, теперь я вижу это, мой плохой. - person ACVM; 23.09.2017