I'm working on an open-source project, and there is an hash_table
that I need to change for a more efficient hash_table, so, I'm trying
to use the header <search.h>
;
The problem, is that I need to overwrite the functions that is already being used all over the project ... but for that, I need to use sizeof(struct hsearch_data) 开发者_StackOverflowbut it doesn't work.
Follow the code:
#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: in the header file, there is a typedef struct hsearch_data hash_table;
I got the error message:
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
Can anybody help me out?
Even though I still have some trouble with hash_table
, I solved this specific problem:
it's something silly ... the
#define _GNU_SOURCE
must be the first thing in the file ... I'm not sure about why you have to do that ... but it works.
Some people said something about __USE_GNU
, this flag is set automatically when you use #define _GNU_SOURCE
And I changed the malloc
to calloc
, it was a good idea!
Apparently, the trouble is that the <search.h>
header on your platform does not define the structure type. As noted in a comment to the question, on a RHEL5 Linux machine, the defines 'struct hsearch_data
' when __USE_GNU
is defined, which is, in turn, defined when _GNU_SOURCE
is defined as you have it. However, not all machines are Linux. I note that POSIX does define the <search.h>
header, but does not specify the structure you are seeking to use.
You will need to track down where the project defines the structure, and decide how you can make that available to this code. It may be simple - if the structure is safely segregated in a header which can be safely included. It may be complex if the header that defines the structure also defines other things which you can't use.
Since you are trying to preserve the same interface as the original code, you should be aiming to use the original header to provide the correct interface definition.
At a guess, you're not supposed to use hsearch_data
yourself, but pointers to hsearch_data
objects. Consequently, the header search.h
would not expose its definition, merely a forward declaration. You are then not able to find its size.
If true, the library is designed for you to use the functions it provides, rather than rolling your own by stealing its datatypes.
The reentrant versions with _r
are GNU extensions to the hash functions in "search.h". If you look into the include file you'd see that they are protected by a macro name __USE_GNU
that doesn't seem to be documented, but that you probably have to set to use them properly. In particular your sizeof
should then work.
But:
- your
malloc
should not be casted. In C you don't do that,void*
can be assigned to any pointer to object. - the line following your
malloc
will not work as you wrote it. This is initializer syntax and not for assignment. - what they mean by zeroing out the initial table for
hcreate_r
is probable to usecalloc
instead ofmalloc
- if you want to do an "absolutely safe" initialization that and have a C99 conforming compiler (e.g gcc or clang) you could do the following assignment with a compound literal
*table = (struct hsearch_data){0};
精彩评论