A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
C gives you two mechanisms for named constants, and they are not interchangeable. The const keyword creates a read-only variable with a type, a scope, and an address. The #define preprocessor macro creates a text substitution that happens before compilation. One is visible to the debugger. The other is not. One respects scope. The other does not. Choosing wrong has consequences for debuggability and for subtle bugs involving pointer semantics.
#include <stdio.h>int main(void) {const int MAX_USERS = 100;const double GRAVITY = 9.81;const char NEWLINE = '\n';printf("Max users: %d\n", MAX_USERS);printf("Gravity: %.2f m/s^2\n", GRAVITY);return 0;}
Attempting MAX_USERS = 200 produces a compile error: assignment of read-only variable. The const qualifier is enforced by the compiler. The variable still occupies storage, still has an address, and still appears in debugger watches. It is a real variable that you promised not to modify.
#include <stdio.h>#define BUFFER_SIZE 256#define PI 3.14159265358979int main(void) {char buf[BUFFER_SIZE];double circumference = 2 * PI * 5.0;printf("Buffer size: %d\n", BUFFER_SIZE);printf("Circumference: %.4f\n", circumference);return 0;}
The -E flag stops after preprocessing. Look at the output: BUFFER_SIZE is gone. Replaced by 256. PI is gone. Replaced by the literal. The compiler never sees the names. The debugger cannot show you what PI is because PI does not exist at compile time. It was a find-and-replace operation.
Use const for typed constants that benefit from scope and debugger visibility. Use #define for array sizes in C89 (where const int cannot be used as an array dimension), for include guards, and for conditional compilation. In C99 and later, const int works as an array size, so the #define advantage there mostly evaporates. The general modern guidance: prefer const unless you specifically need preprocessor behavior.
Never put a semicolon after a #define constant. #define MAX 100; expands to 100; everywhere it appears, creating double-semicolon syntax errors or, worse, empty-statement bugs in if-else chains.
Constants seem trivial until you are debugging a production issue at midnight and the value you need to inspect does not exist in the binary because someone used a macro. Use const. Your future self, staring at a GDB session, will thank you. Next: typedef, which creates type aliases and is the gateway to reading real-world C headers.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.