A generic dynamic array in C that stores no capacity and needs no struct · GitHub
/" data-turbo-transient="true" />
Skip to content
-->
Search Gists
Search Gists
Sign in
Sign up
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
Instantly share code, notes, and snippets.
alurm/README.md
Last active<br>June 13, 2026 02:39
Show Gist options
Download ZIP
Star
(0)
You must be signed in to star a gist
Fork
(0)
You must be signed in to fork a gist
Embed
Select an option
Embed<br>Embed this gist in your website.
Share<br>Copy sharable link for this gist.
Clone via HTTPS<br>Clone using the web URL.
No results found
Learn more about clone URLs
Clone this repository at <script src="https://gist.github.com/alurm/2ca14be134d719fe7431217a6b18d91e.js"></script>
" readonly="readonly" data-autoselect="true" data-target="primer-text-field.inputElement " aria-describedby="validation-a6367f92-0567-47c9-8488-319dd3a5d611" class="form-control FormControl-monospace FormControl-input FormControl-small rounded-left-0 rounded-right-0 border-right-0" type="text" name="gist-share-url-sized-down" />
Save alurm/2ca14be134d719fe7431217a6b18d91e to your computer and use it in GitHub Desktop.
Embed
Select an option
Embed<br>Embed this gist in your website.
Share<br>Copy sharable link for this gist.
Clone via HTTPS<br>Clone using the web URL.
No results found
Learn more about clone URLs
Clone this repository at <script src="https://gist.github.com/alurm/2ca14be134d719fe7431217a6b18d91e.js"></script>
" readonly="readonly" data-autoselect="true" data-target="primer-text-field.inputElement " aria-describedby="validation-30513451-d684-4413-9cde-39df9ce0558a" class="form-control FormControl-monospace FormControl-input FormControl-small rounded-left-0 rounded-right-0 border-right-0" type="text" name="gist-share-url-original" />
Save alurm/2ca14be134d719fe7431217a6b18d91e to your computer and use it in GitHub Desktop.
Download ZIP
A generic dynamic array in C that stores no capacity and needs no struct
Raw
README.md
A generic dynamic array in C that stores no capacity and needs no struct
The following header shows a way to make a generic dynamic array in C with an array of two pointers:
the first pointer stores the length of the dynamic array;
the second pointer points to the data.
So, int *vec[2] = { 0 }; is an empty dynamic array of ints. struct person *people[2] = { 0 }; is an empty dynamic array of people.
(uintptr_t)vec[0] is the length of the array, vec[1] is the array.
The vec_push macro pushes a value at the end of the dynamic array and returns true on success.
This code is C23 with statement expressions (a GNU C feature).
Why is this interesting
First of all, structs aren't used so you don't have to invent names for them (e.g. there is no IntVec). Since a pointer is used to store the length of the dynamic array (as a uintptr_t), this relies on implementation-defined behavior, that is the uintptr_t length read from a pointer must be the same length that was stored.
Second of all, capacity isn't stored at all. Instead, it's computed on demand when the length of the vec is either zero or a power of two. In this case realloc is called with capacity equal to the next power of two greater than the length. The drawback is that it's more difficult to "reserve" elements: during pushing, when the length reaches a power of two, realloc is called for the next power of two no matter what, so a larger manual reservation is effectively discarded.
Raw
main.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.<br>Learn more about bidirectional Unicode characters
Show hidden characters
#include
#include "vec.h"
int main() {
int *ints[2] = { 0 };
for (uintptr_t i = 0; i 5; i++) if (!vec_push(ints, i + 42)) {
return 1;
// 42, 43, 44, 45, 46.
for (uintptr_t i = 0; i (uintptr_t)ints[0]; i++) printf("%d\n", ints[1][i]);
// Shrinking works.
ints[0] = (void *)3;
// You can only reclaim memory down to the next power of two greater than or equal to the length.
// Otherwise pushing will break.
ints[1] = realloc(ints[1], sizeof(**ints) * 4);
// 42, 43, 44.
for (uintptr_t i = 0; i (uintptr_t)ints[0]; i++) printf("%d\n", ints[1][i]);
free(ints[1]);
struct person {
char *name;
int age;
} *people[2] = { 0 };
vec_push(people, ((struct person){ "Bob", 21 }));
vec_push(people, ((struct person){ "Joe", 42 }));
// Bob: 21, Joe: 42.
for (uintptr_t i = 0; i (uintptr_t)people[0]; i++) printf("%s: %d\n", people[1][i].name, people[1][i].age);
free(people[1]);
Raw
vec.h
This file contains hidden or bidirectional Unicode...