2010-01-26 3 views
0

Я хочу «построить» (читай: malloc и memset) мою хэш-таблицу в c. Чтобы сделать это, я создал функцию следующим образом:Могу ли я назначить Java-подобный конструктор в c?

int maketable(struct hash_entry **table, int size){ 

    table = (struct hash_entry **)malloc(size*sizeof(struct hash_entry *)); 
    int i = 0; 
    for (; i<size; i++) { 
     memset(table[i], '\0', sizeof(struct hash_entry *)); 
    } 
    return 0; 

} 

Учитывая, что таблица будет объявлен

struct hash_entry **table[size] 

перед входом в этот код, я ничего не потеряете, когда я вернусь из maketable, правильно?

EDIT: ли прохождение table в maketable() убедиться, что до тех пор, как я могу изменить данные, которые table указывает на изменения будут сохранены?

EDIT II: Я пытаюсь выделить массив указателей на указатели на hash_entries

+1

Я не понимаю. Вы выделяете память на стек для переменной и затем перераспределяете что-то в функции? - Кроме того, 'table' является локальной переменной. Вы выделяете что-то и назначаете его «таблице», которая исчезнет, ​​когда функция вернется, что приведет к утечке памяти. –

+0

Проблема в том, что я тоже не совсем понимаю. Является ли мое объявление структуры hash_entry ** table [size] неявным распределением памяти для меня? В этом случае я все еще должен malloc для hash_entrys, когда я объявляю их, не так ли? –

+1

Объявление выделяет память для массива с размером 'size' указателей на указатели типа' hash_entry' на стек. Он не выделяет память для местоположений, на которые будут ссылаться элементы массива. –

ответ

4

Ваш код присваивает локальной переменной table, вызывающий объект не влияет. Это приводит к утечке памяти.

За пределами функции вы объявили таблицу как массив указателей на указатели struct hash_entry - я предполагаю, что вы просто хотите, чтобы массив указателей содержал элементы хэш-структуры.

Если вы действительно объявляете table в качестве массива, вам не нужно malloc это пространство. Вам просто нужен цикл, чтобы установить для каждого элемента в NULL (не помещать каждый элемент в нули).

Если цель состоит в том, чтобы выделить всю таблицу, это perhps, что вы ищете:

struct hash_entry **table; 
... 
int maketable(struct hash_entry ***table, int size){ 

    *table = malloc(size* sizeof **table); 
    int i = 0; 
    for (; i<size; i++) { 
     (*table)[i] = NULL; 
    } 
    return 0; 
} 

вызов это как

maketable(&table,100); 

Я бы предпочел сделать это вернуть таблицу как так:

struct hash_entry ** maketable(int size){ 
    return calloc(size, sizeof(struct hash_entry *)); 
} 

если декларация struct hash_entry **table[size] действительно то, что вы хотите, вы должны сказать нам, как предполагается, должна выполняться ваша функция maketable() (например, хотите ли вы динамически выделять «массив» как один из элементов в этой таблице?

2

Вам нужно будет присвоить результат malloc к * table - в противном случае он не будет виден за пределами функции.

Кроме того, типичным способом использования этого является объявление указателя на хеш-таблицу и передача адреса этого указателя в функцию.

+0

Как мне это сделать? –

+1

'* table = (struct hash_entry *) malloc ...' –

1

Нет. Ваши типы не совпадают.

Вы пытаетесь выделить таблицу записей хэша (т.е. типа table[i] является struct hash_entry), таблица указателей к hash_entries (т.е. типа table[i] является struct hash_entry *), или что-то еще? Основываясь на том, как читается ваш код, я принимаю первый случай, но дайте мне знать, если это неправильно.

Предположим, что вы будете динамически выделять таблицу struct hash_entry, ваше объявление таблицы в вызывающем должен быть

struct hash_entry *table; // 1 *, no array dimension 

функции должны быть называется в

int result = maketable(&table, number_of_elements); 

и определенной как

int maketable (struct hash_entry **table, size_t size) 
{ 
    int r = 0; 

    // sizeof **table == sizeof (struct hash_entry) 
    *table = malloc(sizeof **table * size); 
    // *ALWAYS* check the result of malloc() 
    if (*table) 
    { 
    size_t i; 
    for (i = 0; i < size; i++) 
     memset(&(*table)[i], 0, sizeof (*table)[i]); 
    r = 1; 
    } 
    return r; 
} 

Несколько вещей, чтобы указать. Прежде всего, не делайте результат malloc(). С C89 вам не нужно, и бросок подавит диагностику, если вы забудете включить stdlib.h или иначе не имеете прототип для malloc() в области. Во-вторых, вы можете использовать оператор sizeof для объектов вместо типов. Это может помочь уменьшить некоторые головные боли обслуживания (то есть, если вы измените тип table в списке параметров, вам не придется менять вызовы sizeof вместе с ним).

Наконец, обратите внимание, что адрес таблицы передается функции; поскольку мы пытаемся записать значение указателя, мы должны передать указатель на этот указатель.

Если вы пытались создать таблицу указателей на struct hash_entry, код в основном то же самое, только дополнительный уровень косвенности:

ваше объявление таблицы в вызывающему должен быть

struct hash_entry **table; // 2 *, no array dimension 

функция должна быть называется, как

int result = maketable(&table, number_of_elements); 

и определяется, как

int maketable (struct hash_entry ***table, size_t size) 
{ 
    int r = 0; 

    // sizeof **table == sizeof (struct hash_entry *) 
    *table = malloc(sizeof **table * size); 
    // *ALWAYS* check the result of malloc() 
    if (*table) 
    { 
    size_t i; 
    for (i = 0; i < size; i++) 
     (*table)[i] = NULL; 
    r = 1; 
    } 
    return r; 
} 

EDIT Была ошибка в maketable примерах; table необходимо разыменовать перед применением индекса, то есть (*table)[i]. Мы применяем индекс к тому, что tableуказывает на, а не на указатель таблицы.

Извините за путаницу.

+0

Я пытаюсь выделить таблицу указателей указателям на hash_entries. –

+0

Затем вам нужно объявить таблицу как 'struct hash_entry *** table;'. Тип параметра в функции должен быть 'struct hash_entry **** table'. Все остальное должно быть таким же, как и во втором примере. –

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