Я не могу использовать sizeof (struct hsearch_data) из <search.h> - PullRequest
1 голос
/ 20 февраля 2011

Я работаю над проектом с открытым исходным кодом, и есть hash_table, который мне нужно изменить на более эффективный hash_table, поэтому я пытаюсь использовать заголовок <search.h>;

Проблема в том, что мне нужно переписать функции, которые уже используются во всем проекте ... но для этого мне нужно использовать sizeof (struct hsearch_data), но он не работает.

Followкод:

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

#define _GNU_SOURCE
#include <search.h>
#include "hashtable.h"

#define MAX_ELEMENTS 100
#define ERROR 2
#define SUCCESS 0

hash_table *new_hash_table()
{
    hash_table *table = (hash_table *) malloc(sizeof(struct hsearch_data));
    *table = {0};   

    int status = hcreate_r(MAX_ELEMENTS, table);

    if (status == 0) {
            hdestroy_r(table);
            return NULL;
    }

    return table; 
}

PS: в заголовочном файле есть typedef struct hsearch_data hash_table;

Я получил сообщение об ошибке:

hashtable.c: In function ‘new_hash_table’:
hashtable.c:18: error: invalid application of ‘sizeof’ to incomplete type ‘struct hsearch_data’ 
hashtable.c:19: error: dereferencing pointer to incomplete type

Может кто-нибудьвыручить меня?

Ответы [ 4 ]

2 голосов
/ 20 февраля 2011

По-видимому, вы не должны использовать hsearch_data сами, но указатели на hsearch_data объекты.Следовательно, заголовок search.h не будет раскрывать свое определение, а будет лишь предварительным объявлением.Тогда вы не сможете найти его размер.

Если true, библиотека предназначена для вас, чтобы использовать функции, которые она предоставляет, вместо того, чтобы использовать свои собственные путем кражи типов данных.

2 голосов
/ 20 февраля 2011

Очевидно, проблема в том, что заголовок <search.h> на вашей платформе не определяет тип структуры. Как отмечено в комментарии к вопросу, на машине с Linux RHEL5 определение 'struct hsearch_data', когда определено __USE_GNU, которое, в свою очередь, определяется, когда _GNU_SOURCE определено так, как у вас. Однако не все машины являются Linux. Я отмечаю, что POSIX определяет заголовок <search.h>, но не определяет структуру, которую вы хотите использовать.

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

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

1 голос
/ 21 февраля 2011

Даже думая, что у меня все еще есть проблемы с hash_table, я решил эту конкретную проблему:

это что-то глупое ...

#define _GNU_SOURCE

должно быть первым вфайл ... Я не уверен, почему вы должны это делать ... но это работает.

некоторые люди говорили что-то о _USE_GNU, этот флаг устанавливается, когда вы используете #define _GNU_SOURCE

И я изменил malloc на calloc, это была хорошая идея!

tks.

1 голос
/ 21 февраля 2011

Повторяющиеся версии с _r являются расширениями GNU для хеш-функций в "search.h".Если вы загляните во включаемый файл, то увидите, что он защищен именем макроса __USE_GNU, которое, по-видимому, не документировано, но вам, вероятно, придется настроить его использование должным образом.В частности, ваш sizeof должен тогда работать.

Но :

  • ваш malloc не должен быть брошен.В C вы не можете этого сделать, void* может быть назначен любому указателю на объект.
  • строка, следующая за вашим malloc, не будет работать так, как вы ее написали.Это синтаксис инициализатора, а не для присваивания.
  • что они означают, обнуляя исходную таблицу для hcreate_r, вероятно, можно использовать calloc вместо malloc
  • , если вы хотитевыполнить «абсолютно безопасную» инициализацию, чтобы и имели соответствующий компилятор C99 (например, gcc или clang), вы можете выполнить следующее назначение с составным литералом *table = (struct hsearch_data){0};
...