A small, header-only C utility library with common macros and helper functions designed to simplify everyday C development tasks.
- Overview
- clibx.h - Main Library
- clibx_print.h - Optional Standalone Printf
- Files
- Build & Run the demos
clibx provides lightweight, macro-based utilities for common C programming patterns, reducing boilerplate and improving code readability. Everything is header-only with zero dependencies beyond the C standard library.
Compile-time calculation of array element count. Only works with stack-allocated arrays.
int arr[] = {1, 2, 3, 4, 5};
size_t len = ARRAY_SIZE(arr); // len = 5
print_int_array(arr, len); // Output: [1, 2, 3, 4, 5]print_int_array(arr, len)- Print integer arrays with comma-separated formattingprint_double_array(arr, len)- Print floating-point arraysprint_char_array(arr, len)- Print character arrays with quotes
Return the smaller or larger of two values (type-agnostic).
int x = MIN(10, 20); // x = 10
int y = MAX(10, 20); // y = 20Restrict a value within a range.
int clamped = CLAMP(25, 0, 15); // Result: 15 (capped at max)
int clamped = CLAMP(-5, 0, 15); // Result: 0 (floored at min)Get the absolute value of a number.
int result = ABS(-42); // result = 42Exchange the values of two variables. Type-safe using __typeof__.
int a = 10, b = 20;
SWAP(a, b);
// Now: a = 20, b = 10Safely allocate memory for a single variable with error checking.
int *ptr = NEW(int);
if (!ptr) {
ERROR("Memory allocation failed");
}
*ptr = 99;
FREE(ptr);Allocate memory for an array.
int *arr = NEW_ARRAY(int, 100);
if (!arr) {
ERROR("Array allocation failed");
}
// Use arr...
FREE(arr); // Sets arr to NULL after freeingSafe free that prevents dangling pointers by setting the pointer to NULL.
FREE(ptr); // Frees memory and sets ptr to NULLPrint colored log messages to stderr.
LOG("Starting process with value: %d", value);
// Output: [LOG] Starting process with value: 42Print an error with file and line number, then exit the program.
if (count < 0) {
ERROR("Invalid count: %d", count);
}
// Output: [ERROR] main.c:42: Invalid count: -5
// Program exits with EXIT_FAILUREIterate from 0 to n-1 using size_t.
FOR(i, 5) {
printf("%zu\n", i); // Prints 0, 1, 2, 3, 4
}Iterate from start to end-1 (exclusive end).
FOR_RANGE(i, 5, 10) {
printf("%zu\n", i); // Prints 5, 6, 7, 8, 9
}Compare two strings for equality (wrapper around strcmp).
if (STREQ(command, "quit")) {
exit(0);
}Expands to the type of the expression x using __typeof__. This is useful for declaring variables with the same type as a given expression.
int value = 5;
TYPE_NAME(value) copy = value; // copy has the same type as valueReturns a string describing the type of x for a small set of built-in types.
Supported types:
intlongfloatdoublechar
int value = 5;
printf("Type of value: %s\n", TYPE_STR(value));
// Output: Type of value: intReturns the compiler's pretty function signature for the expression type. This is useful for debugging and inspecting the type category of a variable or expression.
int value = 5;
printf("Function type: %s\n", TYPE_FUNC(value));
// Output: Function type: const char* main() [with int = int]Read a line of input from stdin, safely removing the trailing newline.
char buffer[256];
printf("Enter your name: ");
read_line(buffer, sizeof(buffer));
printf("Hello, %s!\n", buffer);If not using <stdbool.h>, the library provides:
clibx_bool- Type for boolean valuesclibx_true/clibx_false- Boolean constants (1 and 0)CLIBX_PRINT_BOOL(value)- Print boolean as "true" or "false"
clibx_bool flag = clibx_true;
CLIBX_PRINT_BOOL(flag); // Output: trueclibx_print.h is a completely standalone, optional module that provides a minimal printf implementation using Linux x86-64 syscalls directly. It does not depend on libc's stdio, making it lightweight for minimal environments or educational purposes.
Note: This module is independent and can be used without clibx.h.
This is useful when:
- Building minimal/freestanding C programs
- Learning about syscall-level I/O
- Reducing binary dependencies for embedded scenarios
- Teaching low-level C concepts
Printf-style output to stdout. Supports the following format specifiers:
| Specifier | Type | Example |
|---|---|---|
%d, %i |
Signed decimal integer | clibx_printf("%d\n", -42);-> -42 |
%u |
Unsigned decimal integer | clibx_printf("%u\n", 42);-> 42 |
%o |
Unsigned octal | clibx_printf("%o\n", 82);-> 122 |
%x |
Unsigned hexadecimal (lowercase) | clibx_printf("%x\n", 255);-> ff |
%X |
Unsigned hexadecimal (uppercase) | clibx_printf("%X\n", 255);-> FF |
%p |
Pointer address (hex with 0x prefix) | clibx_printf("%p\n", ptr);-> 0xdeadbeef |
%s |
String | clibx_printf("%s\n", "hello");-> hello |
%c |
Character | clibx_printf("%c\n", 'A');-> A |
%% |
Literal percent | clibx_printf("100%%\n");-> 100% |
#include "clibx_print.h"
clibx_printf("Hello, %s! You have %d points.\n", "Alice", 100);
// Output: Hello, Alice! You have 100 points.
clibx_printf("Hex: %x, Octal: %o, Unsigned: %u\n", 255, 82, 42);
// Output: Hex: ff, Octal: 122, Unsigned: 42
int arr[] = {1, 2, 3};
clibx_printf("Array at: %p\n", (void*)arr);
// Output: Array at: 0x7ffc8b234560Printf-style output to an arbitrary file descriptor. Accepts the same format specifiers as clibx_printf.
clibx_fprintf(2, "Error: %s (code: %d)\n", "Something went wrong", 404); // fd 2 = stderr
clibx_fprintf(1, "Result: 0x%X\n", 0x1234); // fd 1 = stdout- Limited format specifier support (see table above)
- No floating-point formatting (
%f,%e, etc.) - No width/precision modifiers (
.,-,0padding, etc.) - x86-64 Linux only (architecture-specific syscall assembly)
- Not a full libc replacement
| Specifier | Type | Reason |
|---|---|---|
%f, %F |
Decimal floating point | Complex; would require significant code |
%e, %E |
Scientific notation | Complex; requires floating-point handling |
%g, %G |
Shortest of %e or %f | Complex; requires floating-point handling |
%a, %A |
Hexadecimal floating point | Complex; requires floating-point handling |
%n |
Characters written so far | Not supported; dangerous and rarely used |
- Uses direct Linux
writesyscall via inline assembly - No buffering: each call directly writes to the file descriptor
- Minimal footprint and zero stdio dependencies
clibx.h- Main header-only utility libraryclibx_print.h- Optional lightweight printf implementation (standalone, no dependencies on clibx.h)main.demo.c- Example program demonstratingclibx.hfeaturesprint.demo.c- Example ofclibx_print.hREADME.md- This file
Use a standard C compiler such as gcc:
gcc main.demo.c -o main_demo
gcc print.demo.c -o print_demo# to run the main demo
./main_demo
# to run the demo of clibx_print.h
./print_demoThe example program demonstrates:
- Array operations and printing
- Math macros (MIN, MAX, CLAMP, ABS)
- Variable swapping and memory allocation
- Loop helpers and string operations
- User input with
read_line - Logging and error handling
- Both
clibx.handclibx_print.hare header-only with no separate compilation needed clibx_print.his completely optional and can be used independently- This project is intended as a toolkit for small CLI utilities and as a teaching example for macro-based helpers in C
- Fully portable except for
clibx_print.h, which requires x86_64 Linux