Подтвердить что ты не робот

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

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

  • Создайте динамический массив длиной 10, который содержит удвоения, используя таНос.
  • Задайте каждую запись массива j/100 для j = 0,1,..., 9. Затем распечатайте это.
  • Добавьте дополнительную пустую запись в конец массива с помощью realloc.
  • Установите новую запись в 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;

pointer = malloc(2*sizeof(int));

Это не компилируется для меня на Visual Studio 2010, Windows 7. Ошибка: "значение типа void не может быть назначено сущности типа int".

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

4b9b3361

Ответ 1

Вы близко.

В C (по крайней мере, начиная с версии стандарта стандарта 1989 года) литье перед malloc и realloc не нужно, так как C может преобразовывать значения типа void * в int * без трансляции. Это не относится к С++, поэтому на основе ошибки, которую вы получаете, похоже, что вы компилируете этот код как С++, а не 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 не будет.

Ответ 2

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

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

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

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

Ответ 3

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

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

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