assert() / static_assert
A macro that verifies program preconditions at runtime. Defined in <assert.h>, it forces the program to terminate and prints debug information when the condition is false. Since C11, static_assert is also available for compile-time checks.
Syntax
// Runtime assertion. If the condition is false, prints the filename, line number, and expression, then calls abort(). // If NDEBUG is defined, this macro expands to an empty expression and does nothing (for production builds). void assert(scalar expression); // Compile-time assertion (C11 and later). Causes a compilation error if the condition is false. // message is a string literal displayed as the error message. static_assert(constant-expression, message); // Can also be written as _Static_assert (the official C11 keyword).
Switching with NDEBUG
| State | Behavior of assert() |
|---|---|
| NDEBUG not defined (default) | If the condition is false, terminates with abort() and prints the filename, line number, and expression. |
| NDEBUG defined (production build) | assert() expands to an empty expression and does nothing. Zero runtime cost. |
Sample Code
#include <stdio.h>
#include <assert.h>
#include <stdint.h> // Used with static_assert.
// Verify the size of int at compile time using static_assert (C11 and later).
static_assert(sizeof(int) >= 4, "int must be at least 4 bytes");
// A function that checks whether an array index is within valid bounds.
int get_element(int *arr, int size, int index) {
assert(arr != NULL); // Ensure the array pointer is not NULL.
assert(size > 0); // Ensure the size is positive.
assert(index >= 0); // Ensure the index is 0 or greater.
assert(index < size); // Ensure the index is within bounds.
return arr[index];
}
// An example that prevents division by zero.
double safe_divide(double a, double b) {
assert(b != 0.0); // Ensure the divisor is not zero.
return a / b;
}
int main(void) {
int nums[] = {10, 20, 30, 40, 50};
// Normal cases (all assertions pass).
printf("nums[2] = %d\n", get_element(nums, 5, 2)); // Prints "30".
printf("10 / 4 = %.2f\n", safe_divide(10.0, 4.0)); // Prints "2.50".
// Uncommenting the lines below will trigger an assertion failure and terminate the program.
// get_element(nums, 5, 10); // index 10 is out of bounds (assert fails).
// safe_divide(5.0, 0.0); // Division by zero (assert fails).
printf("All checks passed.\n");
return 0;
}
Overview
assert() is a highly effective tool for catching bugs early. It lets you explicitly express preconditions in code — for example, "this value must be positive at this point" or "this pointer can never be NULL here." When an assertion fails, the filename and line number are printed, making it easy to pinpoint the bug.
In production builds, you can disable all assert() calls by defining the NDEBUG macro. With GCC or Clang, use the -DNDEBUG option. This lets you switch between debug and production builds without modifying the code.
Do not write expressions with side effects inside assert(). When NDEBUG is defined, the contents of assert() are removed entirely. Any side effects — such as function calls or variable updates — will also disappear, causing different behavior between debug and production builds.
static_assert() (C11 and later) is evaluated at compile time, so use it for conditions that can be verified at compile time, such as type sizes or alignment. It has zero runtime cost. It cannot be used in environments prior to C11.
For related debug topics, see also 'Preprocessor Directives (#pragma / #error)'.
If you find any errors or copyright issues, please contact us.