#define in C – How Object-Like Macros Work

MAX looks like a variable, prints like a number, and is neither. This question from our C Programming Quiz App is the gentlest preprocessor question in the bank — but each wrong option maps to a real confusion about what #define actually is, and the “easy” answer has more machinery behind it than it looks.

The Quiz Question

#define MAX 100
printf("%d", MAX);

What is printed by this code?

  1. MAX
  2. 100
  3. Compile error
  4. 0

The Correct Answer: 100

#define MAX 100 creates an object-like macro: from that line on, the preprocessor replaces every occurrence of the token MAX with 100 — before the compiler ever sees the code. What actually gets compiled is:

printf("%d", 100);

Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:

$ gcc -ansi -Wall -Wextra max.c && ./a.out
100

You can watch the substitution happen with gcc -E max.c, which stops after the preprocessing stage — the word MAX is already gone.

Why Each Wrong Answer Is Wrong

Why not “MAX”?

Printing the name would require the text to survive into the output — but %d prints an integer, not text, and the name doesn’t even survive into the compiler. One subtlety: macros are not expanded inside string literals. printf("MAX") would print MAX; it’s only the bare token outside quotes that gets replaced.

Why not a compile error?

If the #define were missing, this would fail — MAX would reach the compiler as an undeclared identifier. That’s the diagnostic worth recognizing: an “undeclared identifier” error for something you thought was a macro usually means a missing header or a typo in the name (macros are case-sensitive; max is not MAX).

Why not 0?

0 imagines MAX as an uninitialized variable. But a macro isn’t a variable at all — it has no storage, no address, no type, and no default value. It’s a find-and-replace rule that ceases to exist after preprocessing.

Macro Constants vs const Variables

#define constants have real strengths and real weaknesses versus the alternative, const int MAX = 100;:

#define MAX 100            const int MAX = 100;
─ no type, no scope        ─ typed, obeys block scope
─ invisible in debugger    ─ visible, has an address
─ usable as array size     ─ array size only since C99 (VLA)
  and in #if                 and never in #if
─ can't take &MAX          ─ &MAX works

In C (unlike C++), a const variable is not a constant expression — which is why #define remains the idiom for array dimensions and preprocessor conditionals in C90-compatible code, and why enum { MAX = 100 }; is the popular middle ground for integer constants (typed, scoped, debugger-visible, and a genuine constant expression). Convention: macro names in ALL_CAPS, precisely so readers know they’re looking at textual substitution — the moment a macro takes parameters, a whole extra set of traps opens up, which is the SQ(x) question.

Frequently Asked Questions

What does #define MAX 100 actually do?

It instructs the preprocessor to replace the token MAX with 100 everywhere after the definition (outside string literals), before compilation. No variable is created — the compiler only ever sees the literal 100.

Is a #define constant the same as a const variable?

No. A macro has no type, scope, or storage; a const variable has all three but isn’t a constant expression in C. For integer constants, enum { MAX = 100 }; combines the best of both.

Does #define need a semicolon?

No — and adding one is a classic bug: #define MAX 100; pastes the semicolon too, turning printf("%d", MAX) into printf("%d", 100;) — a compile error at the use site, far from the actual mistake.

Related Reading

Recommended Books

This question is #74 in the C Programming Quiz App — 155 questions with explanations covering preprocessor, pointers, memory, and more.
Download on Google Play →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>