{"id":16017879,"url":"https://github.com/zackradisic/c-template","last_synced_at":"2025-08-26T00:04:08.707Z","repository":{"id":193148759,"uuid":"685341958","full_name":"zackradisic/c-template","owner":"zackradisic","description":"Simple C project starter template","archived":false,"fork":false,"pushed_at":"2023-09-22T12:01:49.000Z","size":15,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-12T15:14:44.074Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zackradisic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-31T02:47:55.000Z","updated_at":"2023-08-31T13:30:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"eebb14e1-38d4-4d75-ac53-236e62a8e8ff","html_url":"https://github.com/zackradisic/c-template","commit_stats":null,"previous_names":["zackradisic/c-template"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zackradisic%2Fc-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zackradisic%2Fc-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zackradisic%2Fc-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zackradisic%2Fc-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zackradisic","download_url":"https://codeload.github.com/zackradisic/c-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241448469,"owners_count":19964466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-08T16:23:56.735Z","updated_at":"2025-03-02T02:27:25.666Z","avatar_url":"https://github.com/zackradisic.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# C project template\n\nSome common code starter code I use in C projects, curated into a project template.\n\nMost of these are borrowed from rsms's [compis](https://github.com/rsms/compis/tree/main) project.\n\n## Arrays\n\nHeap-allocated and dynamically resizable. Internally is just a `ptr`, `len` and `cap`.\n\n```C\n#include \"common.h\"\n#include \"array.h\"\n\ntypedef array_type(u32) u32array_t;\n\nint main() {\n    u32array_t arr = array_empty(u32_arrayt);\n\n    array_push(u32, \u0026arr, 420);\n    u32 val = array_pop(u32, \u0026arr);\n    safecheck(val == 420);\n\n    // Reserve capacity\n    array_reserve(u32, \u0026arr, 64);\n\n    u32array_t second_arr = array_empty(u32_array_t);\n    // Copy all elements from `arr` into `second_arr`\n    array_concat(u32, second_arr, arr);\n}\n```\n\nThere are also array indexing macros that do bounds checking when compiled with -DDEBUG:\n\n```C\nvoid demonstate_array_macros(u32array_t *arr, u32array_t *arr2) {\n    // Bounds-checked when DEBUG is defined\n    u32 val = array_index(u32, arr, 0);\n    u32 *val = array_ref(u32, arr, 420);\n\n    // use the `_checked` suffix to always use bounds checking\n    u32 val1 = array_index_checked(u32, arr, 0);\n    u32 *val1 = array_ref_checked(u32, arr, 420);\n}\n```\n\nThere's also a `slice_t` type (just `ptr` and `len`) which is bidirectionall convertible to/from `array_t`:\n\n```C\narray_t my_arr = array_empty(array_t);\n// array_t is actually a union, so you can get a slice like this:\nslice_t my_slice = my_arr.slice;\n\n// you can define slices like this:\ntypedef slice_type(float) float_slice_t;\n// you can define an array with a slice type too:\ntypedef array_type_with_slice(float, float_slice_t) float_array_t;\n\nfloat_array_t floats = array_empty(float_array_t);\nfloat_slice_t float_slice = floats.slice;\n\n```\n\nAll array macros that don't modify the array work on slices:\n\n```C\nvoid demonstate_slices(float_slice_t slice) {\n    float val = array_index(float, \u0026slice, 0);\n    float *ref = array_ref(float, \u0026slice, 0);\n}\n```\n\n## Common\n\n### Integer types\n\nContains shorter integer type names a la Zig/Rust:\n\n```C\ntypedef uint8_t u8;\ntypedef uint16_t u16;\ntypedef uint32_t u32;\ntypedef uint64_t u64;\ntypedef size_t usize;\n```\n\n### `safecheck()`/`safefail()`\n\nA nicer way to do assertions with formatted strings:\n\n```C\n// First argument is the condition, panics with backtrace\n// if it is false\nsafecheckf(some_val == 420, \"420 != %d\\n\", *some_val);\n```\n\n## Arena\n\nA linear allocator.\n\n### References\n\n- gingerBill's [Memory Allocation Strategies: Linear/Arena Allocators](https://www.gingerbill.org/article/2019/02/08/memory-allocation-strategies-002/)\n- PBR Book's chapter on [Arena-Based Allocation](https://www.pbr-book.org/3ed-2018/Utilities/Memory_Management#Arena-BasedAllocation)\n\n##\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzackradisic%2Fc-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzackradisic%2Fc-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzackradisic%2Fc-template/lists"}