Как мне динамически выделить размер массива? - PullRequest
1 голос
/ 24 апреля 2019
include <stdio.h>

int main() {
   int num = 10;
   int arr[num];
   for(int i = 0; i < num; i++){
     arr[num] = i+1;
   }
}

Какой-то мой коллега говорит, что этот код неверен и незаконен. Однако, когда я запускаю его, он работает без каких-либо ошибок. И он не знает, как объяснить, почему это работает и почему я не должен кодировать, как это. Не могли бы вы мне помочь. Я начинающий, и я хочу изучать C.

Ответы [ 3 ]

0 голосов
/ 24 апреля 2019

Вы изучаете C или C ++?

Ваш коллега имел в виду, что в своем коде вы делаете что-то отличное от того, что вы хотели. Это работает из-за некоторых дополнительных факторов. Потому что стандарты C / C ++ развиваются, как и компиляторы. Позвольте мне показать вам.

Статический массив

Когда вы начинающий, обычно рекомендуется придерживаться концепции, что «типизированный массив заданного размера компиляции» равен int arr[N], где N - это константа . Вы размещаете его в стеке и не управляете его памятью.

В C ++ 11 вы можете использовать constexpr (константное выражение), но все еще не является произвольной переменной.

В C ++ 14 вы можете использовать «простое выражение» для размера, но вы не должны много пробовать, прежде чем получить концепцию массива заранее. Кроме того, компилятор GCC предоставляет расширение для поддержки массивов переменного размера, это может быть объяснением того, «почему код работает вообще».

Примечание: массивы переменного размера не совпадают с динамическими массивами. Это не статические массивы из первой главы путеводителя по C / C ++.

Существует также современный подход - std::array<int, 10>, но опять же, не начинайте с него.

Динамический массив

Когда вам нужно создать массив в runtime , все меняется. Прежде всего, вы выделяете его на heap и либо сами управляете его памятью (если этого не происходит, вы получаете утечку памяти, способ Pure C), либо используете специальные классы C ++, такие как std::vector. Еще раз, векторы должны использоваться после ознакомления с массивами Pure C.

Ваш коллега, должно быть, имел в виду нечто подобное:

int* arr = new int[some_variable]; // this is dynamic array allocation
delete[] arr; // in modern C/C++ you can write "delete arr;" as well

Итак, ваш компилятор заставил его работать именно в этом случае, но вам определенно не следует полагаться на подход, который вы пробовали. Это не распределение массива вообще.

TL; DR:

  • В C ++ массивы переменной длины недопустимы
  • компилятор g ++ допускает массивы переменной длины, потому что C99 допускает их
  • Помните, что C и C ++ - это два разных языка
  • Кажется, кусок кода из вопроса не делает то, что вы хотели, чтобы он делал
  • Как уже упоминалось, должно быть arr[i] = i + 1, вместо этого вы все время присваиваете один и тот же элемент массива
0 голосов
/ 26 апреля 2019

Если вы хотите динамически выделить массив длиной n int s, вам нужно использовать либо malloc, либо calloc.Calloc предпочтительнее для выделения массива, потому что он имеет встроенную проверку переполнения умножения.

int num = 10;
int *arr = calloc(num, sizeof(*arr));
//Do whatever you need to do with arr
free(arr);
arr = NULL;

Всякий раз, когда вы выделяете память с помощью malloc или calloc, всегда не забывайте free, а затем установитеуказатель на NULL для предотвращения случайных, будущих ссылок, а также для предотвращения двойного освобождения.

0 голосов
/ 24 апреля 2019

Хотя этот код не обязательно запрещен, он не будет выполнять то, что вы собираетесь. Когда вы объявляете массив, вы объявляете количество элементов, которые вы хотите сохранить, в этом случае num. Поэтому, когда вы объявляете num = 10 и arr[num], вы получаете массив, который может содержать 10 целых чисел. Массивы C индексируются от 0, поэтому индексы 0-9, а не 1-10. Это, вероятно, то, что они подразумевают под незаконным. Так как вы пишете в arr[num] или arr[10], вы пытаетесь использовать память за пределами памяти, выделенной для массива.

Кроме того, если я правильно понимаю цель программы, вы хотите заполнить массив числами 1-10. Для этого вам нужно получить доступ к каждому индексу по отдельности. Вы почти там, единственная проблема - arr[num] = i + 1;. Как упоминалось ранее, он находится за концом массива. Тем не менее, вы, вероятно, должны использовать i в качестве индекса, поэтому arr[i], потому что это будет обращаться к каждому индексу, 0-9.

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