Generic Hash Table · C11

HashMap
for C

A type-safe, dynamic hash table for C11. Store any type — int, float, string, pointer — with a single unified API. Auto-resizing, FNV-1a hashing, and zero dependencies.

0.75×
Load Factor
8+
Key Types
O(1)
Average Case
main.c
HashMap *dict = hashmap_create();

hashmap_add(dict, "key", "value");
hashmap_add(dict, "Illusionna", 2.718281828);
hashmap_add(dict, -3.1415926, NULL);
hashmap_add(dict, -0.0F, 0.0F);
hashmap_add(dict, NAN, "A value of math NAN");
hashmap_add(dict, 7, 12);
hashmap_add(dict, &dict, "Zolio Marling");

HashMapVariant *key, *value;
hashmap_iter(dict, key, value) {
    hashmap_print_variant(key);
    hashmap_print_variant(value);
}

hashmap_print_view(dict);
hashmap_destroy(dict);
Features

Everything you need.
Nothing you don't.

Built on proven algorithms with a clean, macro-driven interface that feels natural in any C11 codebase.

FNV-1a Hashing
Industry-proven 64-bit Fowler–Noll–Vo hash with a runtime random seed, providing excellent distribution across all key types.
O(k) per key
🔄
Auto Resize
Automatically expands at 75% load and shrinks at 25% load. Bucket count always stays a power of two for fast modulo via bitwise AND.
Non-blocking
🧩
Generic Types
C11 _Generic selects the right variant constructor at compile time. Use strings, ints, floats, or void pointers as keys or values.
Type-safe
🔗
Chained Buckets
Separate chaining with singly-linked lists. Uses the Linus Torvalds double-pointer technique for branch-free node removal.
Collision-safe
🧠
Memory Tracking
Built-in hashmap_print_view() reports exact memory usage: struct, bucket table, nodes, and heap strings — in human-readable units.
Debug-friendly
🛡
Edge Case Safety
Handles NaN float equality, -0.0f hash normalization, NULL pointer keys, string allocation failures, and integer overflow in bucket sizing.
Battle-hardened
API Reference

Clean. Minimal.
Macro-powered.

Six public macros cover everything. Internal functions are prefixed with double underscores and stay out of your way.

hashmap_create Allocates and initializes a new HashMap with 8 buckets and a random seed.
hashmap_add Insert or update a key-value pair. Auto-expands on high load.
hashmap_get Returns a pointer to the HashMapVariant value, or NULL if not found.
hashmap_del Removes a key-value pair. Auto-shrinks when load drops below 25%.
hashmap_contains Returns 1 if the key exists, 0 otherwise. Zero-cost wrapper over get.
hashmap_iter Macro-based iterator. Expands to a for-loop over all live nodes.
hashmap_clear Frees all nodes and resets bucket count to initial size.
hashmap_destroy Frees all memory including the HashMap struct itself.
hashmap_create() example
HashMap *dict = hashmap_create();
if (!dict) {
  fprintf(stderr, "OOM\n");
}

// dict->bucket == 8 (next power of 2)
// dict->seed == random (time ^ ptr)
// dict->count == 0
Internals

How the bucket
table looks.

After inserting keys the table distributes entries across buckets via hash modulo. Resize keeps load between 25% and 75%.

8 ▸ ∞
Initial Buckets
64-bit
Hash Width
×2 / ÷2
Resize Strategy
0 deps
Dependencies
Simulated bucket distribution · 12 entries · 16 buckets
Get Started

Up and running
in minutes.

Two files. Drop them in. Start hashing.

01
Copy the source files
Drop hashmap.h and hashmap.c into your project directory. No build system required.
git clone https://github.com/Illusionna/HashMap.c
02
Include the header
Add the include in any translation unit that needs HashMap access. Compile with -std=c11 or later.
#include "hashmap.h"
03
Compile & link
Link hashmap.c alongside your source. The only standard dependency is libc.
gcc -std=c11 main.c hashmap.c -o app
quick_example.c
#include "hashmap.h"

int main() {
  HashMap *m = hashmap_create();

  hashmap_add(m, "pi", 3.14159);
  hashmap_add(m, 1, "one");
  hashmap_add(m, 2, "two");

  hashmap_print_view(m);

  hashmap_destroy(m);
  return 0;
}