2015-04-15 2 views
0

Я возникла проблемы упаковочных мой мозг вокруг правильного использования указателей с массивами в С.Изменение размера массива в пределах структуры в C

проекта я работаю над строю простой динамический массив и функцию, чтобы идти вместе с этим. Однако, похоже, я не могу найти правильный синтаксис/функции для динамического обновления размера массива. Вот код Релевента:

Создание массива:

struct DArray 
{ 
    TYPE *data;  /* pointer to the data array */ 
    int size;  /* Number of elements in the array */ 
    int capacity; /* capacity ofthe array */ 
}; 


void initDArray(DArray *v, int capacity) 
{ 
    assert(capacity > 0); 
    assert(v!= 0); 
    v->data = (TYPE *) malloc(sizeof(TYPE) * capacity); 
    assert(v->data != 0); 
    v->size = 0; 
    v->capacity = capacity; 
} 


DArray* createDArray(int cap) 
{ 
    assert(cap > 0); 
    DArray *r = (DArray *)malloc(sizeof(DArray)); 
    assert(r != 0); 
    initDArray(r,cap); 
    return r; 
} 

И немного проблемы, в его текущем неработающий формы:

void _DArraySetCapacity(DArray *v, int newCap) 
{ 

    TYPE * newptr = createDArray(newCap); 
    newptr = (TYPE *) malloc(sizeof(TYPE) * newCap); 
    v->capacity = newCap; 
    v->data = newptr; 

} 

Мой метод в том, чтобы создать временный указатель с увеличенными затем скопируйте существующую дату и укажите указатель данных в новом местоположении. Я подозреваю, что, возможно, я рассматриваю проблему совершенно неправильно.

Любые подсказки или указатели (предназначенные для каламбуров) будут оценены по достоинству. Заранее спасибо.

+3

Вы можете прочитать о функции ['realloc'] (http://en.cppreference.com/w/c/memory/realloc).Кроме того, вы [не должны приводить результат 'malloc' (или' realloc')] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858). –

+0

Похоже, вы используете компилятор C++ для компиляции C. (определения struct не являются typedefs в C, в C++ они) – wildplasser

+0

, поэтому вы исправили свою проблему с утверждением, а затем - вы обновили вопрос или приняли ответ? Просто посмотрел - нет, вы не сделали – pm100

ответ

1

Как насчет использования realloc?

: C функции библиотеки недействительными * перераспределить (недействительными * PTR, size_t размера) пытается изменить размер блока памяти, на которую указывает PTR, который был ранее выделенной с помощью вызова таНос или calloc.

1

К счастью, вам не нужно перемещать память вокруг себя: realloc делает это за вас.

В вашем случае типичное использование будет:

v->capacity = newCap; 
v->data = realloc(v->data, newCap * sizeof *v->data); /* same as sizeof(TYPE) */ 

Обратите внимание, что вы не должны (и не должны) бросить результат таНос/calloc или перераспределить.

+0

В то время как вы технически верны, назначение исходного указателя, которое вы перераспределите, может привести к утечке памяти. Подумайте о случае, когда 'realloc' терпит неудачу, тогда исходный указатель будет потерян. –

+0

@JoachimPileborg совершенно верно, но поскольку OP использует 'assert' для проверки своих' malloc', он также может просто использовать 'assert' для результата' realloc' и залога (хотя и нечисто) из программы полностью. – Kninnug

0

Динамические общие массивы на C неожиданно просты.

добавляющим/вставляя элементы:

size_t size = 0, count = 0; 
mytype_t *items; // array of mytype_t 

mytype_t foo1, foo2, foo3; 

carray_grow(items, size, count += 1); // grow to 1 
items[0] = foo3; 

carray_grow(items, size, count += 2); // grow to 3 
carray_insert(items, count, 0, 2); // shift 2 up at 0 
items[0] = foo1; 
items[1] = foo2; 

Удаление элементов:

carray_remove(items, count, 0, 2); // remove 2 at 0 
carray_grow(items, size, count -= 2); // shrink to 1 

Free это полностью?

carray_grow(items, size, count = 0); 

Backend (несколько определяет и одну функцию вперед):

int carray_xgrow(void **datap, size_t *sizep, size_t esize, size_t count); 
// 0 or -1/errno(realloc) 

#define carray_grow(array, size, count) carray_xgrow((void **)&(array), &(size), sizeof((array)[0]), count) 
// 0 or -1/errno(realloc) 

#define carray_move(array, from, to, n) memmove(&(array)[to], &(array)[from], sizeof((array)[0]) * (n)) 
#define carray_insert(array, count, i, n) carray_move(array, i, (i)+(n), (count)-(i)-(n)) 
#define carray_remove(array, count, i, n) carray_move(array, (i)+(n), i, (count)-(i)-(n)) 

int 
carray_xgrow(void **datap, size_t *sizep, size_t esize, size_t count) 
{ 
    assert(datap != NULL); 
    assert(sizep != NULL); 
    assert(esize > 0); 

    size_t size = *sizep; 
    { 
     size_t cap = size/esize; 

     if (cap >= count * 2) // regrow at 1/2 
      cap = 0; 

     while (cap < count) // grow by 3/2 
      cap = (cap < 2) ? (cap + 1) : (cap * 3/2); 

     size = cap * esize; 
    } 

    if (size != *sizep) { 
     if (size) { 
      void *data = realloc(*datap, size); 
      if (data == NULL) return -1; 
      *datap = data; 
      *sizep = size; 
     } 
     else { 
      free(*datap); 
      *datap = NULL; 
      *sizep = 0; 
     } 
    } 
    return 0; 
} 

(размер Примечание в байтах, но капа и кол-во элементов.)

EDIT: удалены мелкие зависимости

Смежные вопросы