Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An object-like macro is a preprocessor directive that binds an identifier to a specific sequence of preprocessing tokens. During the translation phase, the C preprocessor replaces all unquoted occurrences of this identifier in the source code with the defined token sequence before the compiler performs semantic analysis and parsing.
#define IDENTIFIER replacement_list

Mechanics of Substitution

  • Translation Phase: Macro expansion occurs during Translation Phase 4 of the C compilation process. The compiler itself never sees the macro identifier; it only processes the resulting replacement_list.
  • Tokenization: The replacement_list consists of a sequence of preprocessing tokens (e.g., constants, string literals, operators, or other identifiers). If the list is empty, the identifier is replaced by nothing, effectively removing it from the source code.
  • Recursive Expansion: If the replacement_list contains identifiers of other defined macros, the preprocessor will continually expand them. However, if a macro’s identifier appears within its own expansion, it is not expanded a second time, preventing infinite recursion.

Scope and Lifecycle

  • Lexical Scope: The macro becomes active immediately after its #define directive and remains valid until the end of the translation unit (source file) or until it is explicitly revoked.
  • Revocation: The #undef directive terminates the macro’s scope.
#define CAPACITY 500
int x = CAPACITY; /* CAPACITY is expanded to 500 */

#undef CAPACITY
/* CAPACITY is no longer recognized by the preprocessor after this line */
  • Redefinition: An object-like macro cannot be redefined with a different replacement_list unless it is first undefined. Redefining it with the exact same sequence of tokens (including whitespace equivalence) is permitted by the C standard.

Technical Characteristics

  • No Memory Allocation: Because object-like macros are resolved via token substitution prior to compilation, the macro identifiers themselves do not exist at runtime and do not occupy memory addresses.
  • Lvalue Evaluation: While the macro identifier itself is strictly a preprocessor construct, its evaluation as an lvalue depends entirely on its replacement_list. If the substituted tokens form a valid lvalue (e.g., #define ALIAS global_var or #define DEREF (*ptr)), the expanded macro can be placed on the left side of an assignment operator or referenced with the address-of (&) operator. If the tokens form an rvalue (e.g., a numeric constant), it cannot.
  • Type Agnosticism: Macros possess no inherent C data type. Type evaluation occurs only after substitution, when the compiler evaluates the resulting expression based on the injected tokens.
  • String Literal Independence: The preprocessor will not replace macro identifiers that appear inside string literals or character constants. For example, printf("IDENTIFIER"); remains unchanged regardless of the macro definition.
Master C with Deep Grasping Methodology!Learn More