hsearch(3)
๐ hsearch(3) โ hash table management ๐
okay bestie, listen. this is hsearch(3), a page from the Library Functions Manual, and it's literally all about keeping your stuff in a hash table so you can find it again like it's nothing. no cap. let's get into it ๐ซถ
โจ NAME โจ
hcreate, hdestroy, hsearch, hcreate_r, hdestroy_r, hsearch_r โ hash table management. that's the whole vibe. ๐ธ
๐ LIBRARY ๐
Standard C library โ that's libc, link it with -lc. iconic behavior.
๐ง SYNOPSIS ๐ง
#include <search.h>
int hcreate(size_t nel);
void hdestroy(void);
ENTRY *hsearch(ENTRY item, ACTION action);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <search.h>
int hcreate_r(size_t nel, struct hsearch_data *htab);
void hdestroy_r(struct hsearch_data *htab);
int hsearch_r(ENTRY item, ACTION action, ENTRY **retval,
struct hsearch_data *htab);
note the #define _GNU_SOURCE before the second #include โ that's the price of admission for the _r crew, and it points you at feature_test_macros(7). ๐
๐ DESCRIPTION ๐
so the trio hcreate(), hsearch(), and hdestroy() let you create and manage a hash search table full of entries, where each entry is a key (a string) plus some associated data. sounds amazing right? โ ๏ธ the catch: with these three, only one hash table can be in use at a time. one. single. table. monogamy table. ๐
then we have the glow-up versions โ hcreate_r(), hsearch_r(), hdestroy_r() โ the reentrant ones, so your program can run multiple hash search tables at the same time. main character energy for real. the last argument, htab, points to a structure describing which table the function should operate on. and bestie, hear me: the programmer is supposed to treat that structure as opaque โ like, do not try to directly access or poke at the fields in there. hands off. ๐ซ
- first things first โ you gotta create a hash table with
hcreate(). the argumentnelis the maximum number of entries in the table. and no, this maximum cannot be changed later, so choose it wisely ๐ญ. the implementation is allowed to bump this value upward to make the resulting hash table perform better. hcreate_r()does the exact same job ashcreate()but for the table described by the structure*htab. and yes: the structure thathtabpoints at must be zeroed before the first call tohcreate_r(). zero it first, bestie, i'm begging.hdestroy()frees the memory taken up by the hash table thathcreate()made. once you've calledhdestroy(), you can create a new hash table withhcreate()again. โจhdestroy_r()does the analogous thing for a hash table described by*htab, which was previously created usinghcreate_r().
now, the search:
hsearch() searches the hash table for an item with the same key as item โ and "the same" here is decided using strcmp(3) โ and if it works out, it returns a pointer to it. slay.
the argument item is of type ENTRY, which is defined in <search.h> like this:
typedef struct entry {
char *key;
void *data;
} ENTRY;
- the field
keypoints to a null-terminated string, and that's your search key. - the field
datapoints to the data associated with that key.
the argument action decides what hsearch() does after a search comes up empty. it has to be one of these two:
ENTERโ insert a copy ofitem, and return a pointer to the new hash table entry as the function result.FINDโ returnNULL.
(and if action is FIND, then data gets ignored, periodt.)
hsearch_r() is like hsearch() but it operates on the hash table described by *htab. the difference? instead of handing you the pointer as the function result, it puts a pointer to the found item into *retval. โจ
๐ RETURN VALUE ๐
hcreate()andhcreate_r()return nonzero on success. they return 0 on error, and seterrnoto say which error it was.- on success,
hsearch()returns a pointer to an entry in the hash table. hsearch()returnsNULLon error โ that means eitheractionwasENTERand the hash table is full, oractionwasFINDanditemcouldn't be found in the hash table.hsearch_r()returns nonzero on success and 0 on error.- when one of those two errors happens, they set
errnoto indicate the error. ๐
๐ ERRORS ๐
hcreate_r() and hdestroy_r() can fail for this reason:
EINVALโhtabisNULL.
hsearch() and hsearch_r() can fail for these reasons:
ENOMEMโactionwasENTER,keywas not found in the table, and there was no room in the table to add a new entry. ๐ญESRCHโactionwasFIND, andkeywas not found in the table.
heads up: POSIX.1 specifies only the ENOMEM error. the rest are a bonus. ๐
๐ฆ ATTRIBUTES ๐ฆ
for an explanation of the terms used in this section, go see attributes(7). (it's giving "read the fine print" but make it cute.)
hcreate(),hsearch(),hdestroy()โ Thread safety:MT-Unsafe race:hsearchhcreate_r(),hsearch_r(),hdestroy_r()โ Thread safety:MT-Safe race:htab
๐ STANDARDS ๐
hcreate(),hsearch(),hdestroy()โ POSIX.1-2008.hcreate_r(),hsearch_r(),hdestroy_r()โ GNU.
๐ HISTORY ๐
hcreate(),hsearch(),hdestroy()โ SVr4, POSIX.1-2001.hcreate_r(),hsearch_r(),hdestroy_r()โ GNU.
๐ฅ NOTES ๐ฅ
hash table implementations are usually more efficient when the table has enough free space to keep collisions to a minimum. typically that means nel should be at least 25% larger than the maximum number of elements you actually expect to store in the table. do the math, bestie. ๐งฎ
and now the part that gets everybody: hdestroy() and hdestroy_r() do not free the buffers pointed to by the key and data elements of the hash table entries. why? because it literally can't โ it has no idea whether those buffers were allocated dynamically. so if those buffers need freeing (say, because your program keeps creating and destroying hash tables instead of making one single table whose lifetime matches the whole program), then your program has to keep its own bookkeeping data structures so it can free them itself. the manual is not gonna do your homework for you. ๐
๐ BUGS ๐
okay so here's the tea: SVr4 and POSIX.1-2001 specify that action is only significant for unsuccessful searches, which means an ENTER shouldn't do anything at all for a successful search. but in libc and glibc (before glibc 2.3), the implementation violates the specification and updates the data for the given key in that case. ๐ not it.
also: individual hash table entries can be added, but not deleted. that's just the rules. ๐
๐ธ EXAMPLES ๐ธ
this program inserts 24 items into a hash table and then prints some of them. iconic.
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
static char *data[] = { "alpha", "bravo", "charlie", "delta",
"echo", "foxtrot", "golf", "hotel", "india", "juliet",
"kilo", "lima", "mike", "november", "oscar", "papa",
"quebec", "romeo", "sierra", "tango", "uniform",
"victor", "whisky", "x-ray", "yankee", "zulu"
};
int
main(void)
{
ENTRY e;
ENTRY *ep;
hcreate(30);
for (size_t i = 0; i < 24; i++) {
e.key = data[i];
/* data is just an integer, instead of a
pointer to something */
e.data = (void *) i;
ep = hsearch(e, ENTER);
/* there should be no failures */
if (ep == NULL) {
fprintf(stderr, "entry failed\n");
exit(EXIT_FAILURE);
}
}
for (size_t i = 22; i < 26; i++) {
/* print two entries from the table, and
show that two are not in the table */
e.key = data[i];
ep = hsearch(e, FIND);
printf("%9.9s -> %9.9s:%d\n", e.key,
ep ? ep->key : "NULL", ep ? (int) ep->data : 0);
}
hdestroy();
exit(EXIT_SUCCESS);
}
๐ SEE ALSO ๐
bsearch(3), lsearch(3), malloc(3), tsearch(3) โ go read those next, they're the squad. ๐ซถ
and that's the whole page, bestie!! this was Linux man-pages 6.20, dated 2026-02-08, and the page is hsearch(3). go forth and hash responsibly ๐
โจ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: GPL-2.0-or-later
- Copyright 1993, Ulrich Drepper <drepper@redhat.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms