HOWTO · C
How to Implement Dictionary in C
This article introduces how to implement dictionary in C
On this page
ISO C does not define a built-in dictionary type. If your target environment provides the POSIX hsearch interface, its hash-table routines offer one way to store and retrieve key-value entries. The example below creates a table, inserts two entries, looks up a present and an absent key, checks the returned pointers, and releases the table. It demonstrates one approach rather than every possible dictionary design.
Use POSIX hsearch routines to implement a dictionary in C
hcreate, hsearch, and hdestroy are POSIX routines declared by <search.h>, not ISO C library functions. Availability depends on the target operating system and C library, so confirm that your environment provides this interface before using the example. The POSIX specification for hcreate and hsearch defines the interface and is a place to check its requirements. The packet does not identify a specific platform or library version.
Create a hash table and add entries with hcreate and hsearch
Call hcreate once to create a table with a requested capacity. It returns nonzero on success and zero if it cannot create the table. ENTRY holds a char * key and a void * data pointer. Pass an ENTRY and an ACTION value to hsearch: ENTER requests insertion, while FIND requests lookup. A successful call returns a pointer to an entry; a failed call returns NULL.
Run this example:
#define _XOPEN_SOURCE 700
#include <search.h>
#include <stdio.h>
int main(void) {
if (hcreate(4) == 0) {
fputs("could not create table\n", stderr);
return 1;
}
ENTRY item = {"language", "C"};
if (hsearch(item, ENTER) == NULL) {
fputs("could not insert language\n", stderr);
hdestroy();
return 1;
}
item.key = "standard";
item.data = "POSIX";
if (hsearch(item, ENTER) == NULL) {
fputs("could not insert standard\n", stderr);
hdestroy();
return 1;
}
ENTRY query = {"language", NULL};
ENTRY *found = hsearch(query, FIND);
if (found == NULL) {
puts("language: not found");
} else {
printf("language: %s\n", (char *)found->data);
}
query.key = "compiler";
found = hsearch(query, FIND);
if (found == NULL) {
puts("compiler: not found");
} else {
printf("compiler: %s\n", (char *)found->data);
}
hdestroy();
return 0;
}
language: C
compiler: not found
Look up keys and handle missing entries
The first FIND call searches for language, which the program inserted with the value C; the second searches for compiler, which it did not insert. Each result is checked before the program reads data, so a NULL result takes the “not found” path safely. If a lookup for a key that should exist returns NULL, the example still avoids dereferencing it and reports the result. Adapt the messages or return policy to suit your application.
hsearch also returns NULL when an insertion cannot be completed, so check each ENTER result before continuing. The example handles creation and insertion failures by writing a diagnostic to stderr, releasing a table that was already created, and returning a failure status. Keep these checks close to each operation so later code only reads an entry after confirming its pointer.
Free the table and understand its limits
Call hdestroy when the table is no longer needed. It releases the table, but the caller remains responsible for dynamically allocated key or value storage referenced by entries; keep those pointers and free the owned allocations separately. The example uses string literals, so it has no such allocations to release. The POSIX interface shown here does not provide an operation for removing an individual entry. Choose an adequate capacity when creating the table: the requested capacity is passed to hcreate, and this interface does not offer a resize operation in the workflow shown.