Динамический массив в C – Является ли мое понимание malloc и realloc правильным?

Я изучаю, как создавать динамические массивы 1D в C. В приведенном ниже коде делается попытка сделать следующее:

  1. Используя malloc , создайте динамический массив длиной 10 , который содержит значения типа double .
  2. Задайте каждую запись массива j/100 для j = 0, 1,..., 9 . Затем распечатайте его.
  3. Добавьте дополнительную пустую запись в конец массива с помощью realloc .
  4. Установите новую запись в j/100 и распечатайте каждую запись снова.

Тестирование:

  double* data = (double*)malloc(10*sizeof(double)); for (j=0;j<10;j++) { data[j]= ((double)j)/100; printf("%g, ",data[j]); } printf("\n"); data = (double*)realloc(data,11*sizeof(double)); for (j=0;j<11;j++) { if (j == 10){ data[j]= ((double)j)/100; } printf("%g, ",data[j]); } free((void*) data); 

Вопросы

  1. Правильно ли я кодирую это?

  2. Учебники, которые я нашел, используют malloc не ставя перед собой (double*) . Например,

    int * указатель;
    pointer = malloc (2 * sizeof (int));

Это не компилируется для меня на Visual Studio 2010, Windows 7. Сообщение об ошибке

Значение типа void не может быть присвоено сущности типа int .

Почему это работает для этих учебных пособий, а не для меня? Правильно ли я предполагаю, что это связано с тем, что компиляторы, которые они используют, автоматически заполняют (int*) для них в моем примере?

Вы близки.

В C (по крайней мере, начиная с версии стандарта стандарта 1989 года) отливка перед malloc и realloc не нужна, поскольку C может преобразовывать значения типа void * в int * без приведения. Это не относится к C ++, поэтому, основываясь на полученной ошибке, похоже, что вы компилируете этот код как C ++, а не C. Проверьте документацию для VS2010, чтобы определить, как скомпилировать код как C.

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

 double *data = malloc(10 * sizeof *data); 

Поскольку тип данных выражения *data double , sizeof *data эквивалентны sizeof (double) . Это также означает, что вам не нужно настраивать вызовы malloc если тип data изменяется.

Что касается вызова realloc , безопаснее назначить результат временному значению указателя. realloc вернет NULL, если он не может расширить буфер, поэтому безопаснее писать

 double *tmp; ... tmp = realloc(data, 11 * sizeof *data); if (!tmp) { // could not resize data; handle as appropriate } else { data = tmp; // process extended buffer } 

Имейте в виду, что поддержка Microsoft для C заканчивается версией языка 1989 года; с тех пор было два пересмотра языкового стандарта, которые внедрили некоторые новые функции и устарели старые. Поэтому, в то время как некоторые компиляторы C поддерживают функции C99, такие как смешанные объявления и код, массивы переменной длины и т. Д., VS2010 не будет.

1) Я кодирую это право?

В основном. Но data = (double*)realloc(data,11*sizeof(double)); теряет ссылку на выделенную память, если сбой realloc , вы должны использовать временный указатель для хранения возвращаемого значения realloc и проверить, является ли он NULL (и вы также должны проверить возвращаемое значение malloc ).

2) Учебники, которые я нашел, используют malloc, не ставя перед собой (double *).

В C malloc возвращает void* который может быть неявным образом преобразован в любой другой тип указателя, поэтому никакого приведения не требуется (и широко обескуражен, поскольку кастинг может скрыть ошибки). Visual Studio, по-видимому, скомпилирует код как C ++, где требуется актерский состав.

В C вы не должны указывать возвращаемое значение malloc() .

Кроме того, это плохая идея кодировать тип в аргументе malloc() . Это лучший способ:

 double* data = malloc(10 * sizeof *data);