A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
assert is a macro that checks a condition at runtime. If the condition is false, it prints the failed expression, the source file, and the line number to stderr, then calls abort. If the condition is true, it does nothing. It is the cheapest form of runtime verification: a single comparison in debug builds, zero cost in release builds. Defining NDEBUG before including assert.h removes all assert calls at compile time. They vanish. No comparison. No branch. No code.
#include <stdio.h>#include <assert.h>#include <stdlib.h>int divide(int a, int b) {assert(b != 0);return a / b;}int *create_array(int n) {assert(n > 0);int *arr = malloc(n * sizeof(int));assert(arr != NULL);return arr;}int main(void) {printf("10 / 2 = %d\n", divide(10, 2));int *arr = create_array(5);arr[0] = 42;printf("arr[0] = %d\n", arr[0]);free(arr);printf("About to divide by zero...\n");fflush(stdout);printf("10 / 0 = %d\n", divide(10, 0));return 0;}
The assertion message includes the function name, the file, the line number, and the exact expression that failed. You know immediately where the invariant was violated and what the invariant was. No debugger needed. No printf debugging. The assertion told you everything.
#define NDEBUG#include <stdio.h>#include <assert.h>int main(void) {assert(1 == 0);printf("This prints because assert is disabled.\n");return 0;}
With NDEBUG, the assert macro expands to nothing. The b != 0 check is gone. The division by zero proceeds and the hardware raises SIGFPE instead. The assert was the safety net. In release builds, you need a different defense: an explicit if check that returns an error code. assert is for catching programmer errors during development. It is not for handling runtime errors in production.
Never put expressions with side effects inside assert. assert(x++ > 0) increments x in debug builds but not in release builds. The program behaves differently depending on whether NDEBUG is defined. Put side-effect-free conditions in assert. Put side effects outside.
assert is your development-time safety net. Sprinkle it liberally at function entry points, after allocations, and before operations with preconditions. Remove it in release builds with NDEBUG. Replace it with explicit error handling for conditions that can occur in production. Next: clearing the input buffer, the problem that plagues every scanf-based program.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.