12 KiB
gcml.h
Documentation
gcml.h
is a comprehensive C/C++ header file that provides a collection of powerful and versatile macros designed to simplify common programming tasks. These macros enhance code readability, maintainability, and efficiency by encapsulating repetitive patterns and providing utility functions for various operations such as debugging, logging, memory management, and more.
Table of Contents
- General Utility Macros
- Debugging and Logging Macros
- Assertion Macros
- Stringification Macros
- Token Pasting Macros
- Memory Management Macros
- Type Casting Macros
- Bit Manipulation Macros
- Compile-Time Assertion Macro
- Deprecation Warning Macros
- Loop Macros
- Swap Macros
- Execute Once Macros
- Additional Utility Macros
- Utility Macros
- Best Practices and Considerations
1. General Utility Macros
MIN(a, b)
Description:
Returns the smaller of two values a
and b
.
Usage Example:
int a = 5, b = 10;
int min_val = MIN(a, b); // min_val = 5
MAX(a, b)
Description:
Returns the larger of two values a
and b
.
Usage Example:
int a = 5, b = 10;
int max_val = MAX(a, b); // max_val = 10
ARRAY_SIZE(arr)
Description:
Calculates the number of elements in an array arr
.
Usage Example:
int arr[] = {1, 2, 3, 4, 5};
size_t size = ARRAY_SIZE(arr); // size = 5
UNUSED(x)
Description:
Suppresses compiler warnings for unused variables x
.
Usage Example:
void func(int used, int unused) {
UNUSED(unused);
// Function implementation
}
ALIGN_UP(x, align)
Description:
Aligns a value x
upwards to the nearest multiple of align
.
Usage Example:
size_t aligned = ALIGN_UP(13, 8); // aligned = 16
ALIGN_DOWN(x, align)
Description:
Aligns a value x
downwards to the nearest multiple of align
.
Usage Example:
size_t aligned = ALIGN_DOWN(13, 8); // aligned = 8
2. Debugging and Logging Macros
DEBUG_PRINT(fmt, ...)
Description:
Prints debug messages with file name, line number, and function name. Only active when DEBUG
is defined.
Usage Example:
DEBUG_PRINT("Value of x: %d", x);
LOG_INFO(fmt, ...)
Description:
Logs informational messages to stdout
.
Usage Example:
LOG_INFO("Application started successfully.");
LOG_WARN(fmt, ...)
Description:
Logs warning messages to stderr
.
Usage Example:
LOG_WARN("Low memory detected.");
LOG_ERROR(fmt, ...)
Description:
Logs error messages to stderr
.
Usage Example:
LOG_ERROR("Failed to open file: %s", filename);
LOG_FATAL(fmt, ...)
Description:
Logs fatal error messages to stderr
and exits the program.
Usage Example:
LOG_FATAL("Unrecoverable error occurred.");
3. Assertion Macros
ASSERT(cond, fmt, ...)
Description:
Asserts a condition cond
and logs an error message if the condition is false. Only active when NDEBUG
is not defined.
Usage Example:
ASSERT(ptr != NULL, "Pointer 'ptr' should not be NULL.");
4. Stringification Macros
STRINGIFY(x)
Description:
Converts a macro argument x
to a string literal.
Usage Example:
#define VERSION 1
const char* version_str = STRINGIFY(VERSION); // "1"
TOSTRING(x)
Description:
Ensures that x
is expanded before stringification.
Usage Example:
#define VERSION_MAJOR 2
#define VERSION_MINOR 5
const char* version = TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR); // "2.5"
5. Token Pasting Macros
CONCAT(a, b)
Description:
Concatenates two tokens a
and b
.
Usage Example:
int CONCAT(temp, 1) = 10; // Expands to temp1
CONCAT3(a, b, c)
Description:
Concatenates three tokens a
, b
, and c
.
Usage Example:
int CONCAT3(var, _, 1) = 20; // Expands to var_1
6. Memory Management Macros
SAFE_MALLOC(ptr, size)
Description:
Allocates memory of size
bytes and assigns it to ptr
. Logs a fatal error and exits if allocation fails.
Usage Example:
int *array = NULL;
SAFE_MALLOC(array, sizeof(int) * 10);
// Use array...
SAFE_FREE(array);
SAFE_CALLOC(ptr, count, type)
Description:
Allocates zero-initialized memory for count
elements of type type
and assigns it to ptr
. Logs a fatal error and exits if allocation fails.
Usage Example:
int *array = NULL;
SAFE_CALLOC(array, 10, int);
// Use array...
SAFE_FREE(array);
SAFE_FREE(ptr)
Description:
Frees the memory pointed to by ptr
and sets ptr
to NULL
to prevent dangling pointers.
Usage Example:
SAFE_FREE(array);
7. Type Casting Macros
SAFE_CAST(ptr, type)
Description:
Safely casts a pointer ptr
to a specified type type
.
Usage Example:
void *generic_ptr = malloc(sizeof(int));
int *int_ptr = SAFE_CAST(generic_ptr, int*);
8. Bit Manipulation Macros
SET_BIT(x, pos)
Description:
Sets the bit at position pos
in variable x
.
Usage Example:
unsigned int flags = 0;
SET_BIT(flags, 2); // Sets the 3rd bit
CLEAR_BIT(x, pos)
Description:
Clears the bit at position pos
in variable x
.
Usage Example:
CLEAR_BIT(flags, 2); // Clears the 3rd bit
TOGGLE_BIT(x, pos)
Description:
Toggles the bit at position pos
in variable x
.
Usage Example:
TOGGLE_BIT(flags, 1); // Toggles the 2nd bit
CHECK_BIT(x, pos)
Description:
Checks if the bit at position pos
in variable x
is set. Returns a non-zero value if set, zero otherwise.
Usage Example:
if (CHECK_BIT(flags, 1)) {
LOG_INFO("Bit 1 is set.");
}
9. Compile-Time Assertion Macro
STATIC_ASSERT(expr, msg)
Description:
Performs a compile-time assertion to ensure that expr
is true. If not, compilation fails with the message msg
.
Usage Example:
STATIC_ASSERT(sizeof(int) == 4, "Integer size is not 4 bytes.");
10. Deprecation Warning Macros
DEPRECATED(msg)
Description:
Marks a function or variable as deprecated with a custom message msg
. This provides a compiler warning when the deprecated entity is used.
Usage Example:
DEPRECATED("Use new_function() instead.")
void old_function() {
LOG_WARN("This function is deprecated.");
}
11. Loop Macros
FOREACH(item, array)
Description:
Iterates over each element in an array array
, assigning each element's address to item
.
Usage Example:
int arr[] = {1, 2, 3, 4, 5};
int *item;
FOREACH(item, arr) {
LOG_INFO("Array element: %d", *item);
}
REPEAT(n, block)
Description:
Repeats a block of code n
times.
Usage Example:
REPEAT(3, {
LOG_INFO("Repeating this message.");
});
12. Swap Macros
SWAP(a, b)
Description:
Swaps the values of two variables a
and b
. Both variables must be of the same type.
Usage Example:
int a = 10, b = 20;
SWAP(a, b);
// Now a = 20, b = 10
SWAP_INPLACE(a, b)
Description:
Swaps the values of two integer variables a
and b
without using a temporary variable. Uses XOR bitwise operations.
Usage Example:
int x = 5, y = 10;
SWAP_INPLACE(x, y);
// Now x = 10, y = 5
Note: This macro is limited to integer types and should be used with caution to avoid undefined behavior.
13. Execute Once Macros
DO_ONCE(block)
Description:
Executes a block of code block
only once, regardless of how many times the macro is called.
Usage Example:
DO_ONCE({
LOG_INFO("This message is printed only once.");
});
DO_ONCE({
LOG_INFO("This message will not be printed again.");
});
EXECUTE_ONCE(block)
Description:
Creates a do-while
loop that executes a block of code block
exactly once.
Usage Example:
EXECUTE_ONCE({
initialize_system();
});
14. Additional Utility Macros
SAFE_REALLOC(ptr, size)
Description:
Reallocates memory for pointer ptr
to a new size size
bytes. Logs a fatal error and exits if reallocation fails.
Usage Example:
int *data = malloc(5 * sizeof(int));
// Initialize data...
// Reallocate to hold more integers
SAFE_REALLOC(data, 10 * sizeof(int));
// Use the reallocated data...
SAFE_FREE(data);
UNUSED_FUNCTION
Description:
Marks a function as unused to suppress compiler warnings about unused functions.
Usage Example:
UNUSED_FUNCTION void debug_helper() {
DEBUG_PRINT("This is a debug helper function.");
}
TO_STRING(value)
Description:
Converts a value value
to a string at compile time.
Usage Example:
#define VERSION_MAJOR 2
#define VERSION_MINOR 5
const char* version = TO_STRING(VERSION_MAJOR) "." TO_STRING(VERSION_MINOR);
// version = "2.5"
UNIQUE_ID(prefix)
Description:
Generates a unique identifier by appending the current line number to a given prefix
.
Usage Example:
int UNIQUE_ID(temp_) = 100; // Expands to temp_23 if on line 23
FORCE_CAST(value, type)
Description:
Forces a value value
to evaluate to a specific type type
without altering its binary representation.
Usage Example:
float f = 3.14f;
int i = FORCE_CAST(f, int); // Reinterprets the bits of f as an int
Warning:
This macro performs a low-level operation and can lead to undefined behavior if misused.
IS_ALIGNED(ptr, align)
Description:
Checks if a pointer ptr
is aligned to a specified boundary align
. Returns a non-zero value if aligned, zero otherwise.
Usage Example:
int x;
if (IS_ALIGNED(&x, 4)) {
LOG_INFO("Variable x is 4-byte aligned.");
}
COUNT_SET_BITS(x)
Description:
Counts the number of bits set to 1
in the integer x
.
Usage Example:
unsigned int flags = 0b1011;
int count = COUNT_SET_BITS(flags); // count = 3
CEIL_DIV(numerator, denominator)
Description:
Calculates the ceiling of the division between two integers numerator
and denominator
.
Usage Example:
int pages = CEIL_DIV(total_items, items_per_page);
CONCAT_WITH_UNDERSCORE(a, b)
Description:
Concatenates two tokens a
and b
with an underscore _
separating them.
Usage Example:
int CONCAT_WITH_UNDERSCORE(var, 1) = 50; // Expands to var_1
15. Utility Macros
OFFSET_OF(type, member)
Description:
Calculates the byte offset of a member member
within a struct of type type
.
Usage Example:
typedef struct {
int id;
char name[50];
} Person;
size_t offset = OFFSET_OF(Person, name); // Offset of 'name' within 'Person'
CONTAINER_OF(ptr, type, member)
Description:
Retrieves the pointer to the containing struct from a member pointer ptr
. Given the type type
and member member
, it calculates the address of the parent struct.
Usage Example:
typedef struct {
int id;
char name[50];
} Person;
Person person = {1, "Alice"};
int *id_ptr = &person.id;
Person *p = CONTAINER_OF(id_ptr, Person, id);
// p points to 'person'