указатель realloc int присутствует в структуре [C]

Я хочу выделить целочисленный указатель внутри структуры.

Если в будущем мне нужно будет расширить массив, я использую realloc.

что-то вроде этого:

typedef struct {
   int *temp,count
}foo;

main()
{
    foo *fake = (foo*)malloc(1*sizeof(foo));
    fake.count = 0;

    ++(fake.count);
    fake.temp = (int*)malloc((fake.count)*sizeof(int));

    /* I do something */

    /*now i want to realloc "temp" to ++(fake.count) */

Этот способ сделать это правильно?

    ++(fake.count);
    fake.temp = (int*)realloc(fake.temp,(fake.count)*sizeof(int));

person sam32    schedule 31.07.2012    source источник
comment
должно быть как fake->count fake->temp и т.д.   -  person Aftnix    schedule 31.07.2012


Ответы (3)


В принципе, да.

Однако вы должны убедиться, что ваш код выдерживает возможные ошибки в realloc, например:

int * p = realloc(fake->temp, (fake->count + 1) * sizeof(int));
if (p) { fake->temp = p; ++fake->count; }
else   { /* error! But fake was untouched. */ }

Кроме того, вы должны сказать int main(void) для объявления вашей основной функции. Наконец, вам не следует приводить результат malloc или realloc, поскольку void* неявно преобразуется в любой другой указатель объекта.

Еще один: ваш стиль кодирования действительно трудно читать другим. Я бы написал определение структуры следующим образом:

typedef struct foo_
{
    int * temp;
    int   count;
} foo;

И еще один: нужно ли динамически выделять fake? Если нет, автоматическую переменную foo fake; может быть проще поддерживать. В любом случае, если вы хотите выделить его динамически, не применяйте и не повторяйте тип, например:

foo * fake = malloc(sizeof *fake);
// or:       calloc(1, sizeof *fake);      // this will zero out the memory
person Kerrek SB    schedule 31.07.2012
comment
Спасибо за ответ. Вы хотите сказать, что я должен использовать другой указатель, который в вашем случае p, чтобы перераспределить fake.temp, а позже, если перераспределение пройдет успешно, заставить fake.temp удерживать перераспределенную память p. Если я не сделаю этого таким образом, например, используя другой указатель int, вызовет ли это в будущем ошибки сегментации, если я попытаюсь получить доступ к перераспределенной памяти или изначально распределенной памяти?? - person sam32; 31.07.2012
comment
@ sam32: не ошибка сегментации, но результатом realloc может быть NULL, и если вы немедленно перезапишете исходный указатель, вы никогда больше не сможете достичь исходного распределения. Как только realloc возвращает ненулевой указатель, его можно безопасно использовать. - person Kerrek SB; 31.07.2012
comment
Мне нужно выделить его динамически. Я не совсем понял вашу мысль о том, что не приводить и не повторять тип. Не могли бы вы уточнить это. Спасибо! - person sam32; 31.07.2012
comment
@sam32: Моя последняя строка кода с malloc содержит только имя типа (то есть foo) один раз, а не три раза, как в вашем коде. И актерского состава нет. - person Kerrek SB; 01.08.2012

  1. Вам не нужно приводить возвращаемое значение из malloc или realloc в программе на C.
  2. Не назначайте напрямую результат вашего вызова realloc одной и той же переменной. Если это не удастся, вы потеряете исходное распределение. Вместо этого сделайте что-то вроде этого:

    void *err = realloc(pointer, newSize);
    if (err != NULL)
    {
        pointer = err;
    }
    
  3. Придирка - умножение на 1 выглядит странно.
person Carl Norum    schedule 31.07.2012

Трудно сказать, будет ли нормально делать realloc таким образом, не зная, что такое I do something. Но можно начать с этого....

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

typedef struct {
 int *temp,count;
 }foo;

extern char etext, edata, end;
int main()
{
   printf("Heap before first malloc %p\n", sbrk(0));

   foo *fake = malloc(1*sizeof(foo));

   printf("heap after first malloc %p\n", sbrk(0));

   fake->count = 0;
   ++(fake->count);
   fake->temp = malloc((fake->count)*sizeof(int));
   printf("heap after second malloc %p\n", sbrk(0));

   fake->count += 2;
   fake->temp = realloc(fake->temp, (fake->count) * sizeof(int));
   printf("count %d\n", fake->count);

   printf("heap after realloc %p\n", sbrk(0));
   printf("program text segment(etext)      %10p\n", &etext);
   printf("initialized data segment(edata)  %10p\n", &edata);
   printf("uninitialized data segment (end) %10p\n", &end);

   return 0;
}

Это также выведет ваши адреса кучи.

Heap before first malloc 0x239b000
heap after first malloc 0x23bc000
heap after second malloc 0x23bc000
count 3
heap after realloc 0x23bc000
program text segment(etext)        0x400816
initialized data segment(edata)    0x600bc4
uninitialized data segment (end)   0x600bd8
  1. Вам не нужен гипс для malloc().

  2. Подумываю о calloc(), чтобы очистить память. При перераспределении вы можете получить неправильно инициализированный блок памяти. (например, недавно освобожденные блоки).

  3. Всегда проверяйте возвращаемое значение realloc() перед его использованием. вероятность неудачного realloc() довольно высока, чем malloc().

person Aftnix    schedule 31.07.2012