C #define Directive

Definition

The #define directive is a preprocessor command that creates macros. It performs pure textual substitution before the compiler translates the source code. Unlike variables or functions, macros are not type-checked, do not occupy memory, and are evaluated entirely during the preprocessing phase. They are used for constants, code inlining, conditional compilation, and metaprogramming patterns.

Syntax & Macro Types

// Object-like macro (constant or snippet)
#define MAX_BUFFER 1024
#define ENABLE_DEBUG
// Function-like macro (parameterized substitution)
#define SQUARE(x) ((x) * (x))
// Multi-line macro (backslash continuation)
#define LOG_ERROR(msg) do { \
fprintf(stderr, "[ERROR] %s\n", msg); \
} while(0)
// Undefining a macro
#undef MAX_BUFFER

Preprocessing Mechanics

  1. Scanning: The preprocessor reads the source file sequentially.
  2. Substitution: Every occurrence of the macro identifier is replaced with its replacement text.
  3. Expansion Rules:
  • Replacement text is rescanned for further macro expansions.
  • A macro is not expanded recursively within its own replacement text (prevents infinite loops).
  • Arguments are fully expanded before substitution.
  1. Tokenization: Whitespace is generally ignored unless used for stringification or token pasting.

Advanced Operators

OperatorNameBehaviorExample
#StringificationConverts macro argument to a quoted string#define STR(x) #xSTR(hello)"hello"
##Token PastingConcatenates two tokens into one#define CONCAT(a,b) a##bCONCAT(var,1)var1
#include <stdio.h>
#define PRINT_VAR(v) printf(#v " = %d\n", v)
#define CREATE_FIELD(type, name) type name##_field
int main(void) {
int count = 42;
PRINT_VAR(count);          // Output: count = 42
CREATE_FIELD(int, data);   // Declares: int data_field;
return 0;
}

Rules & Constraints

  • No Type Safety: Macros operate on raw tokens. The compiler sees only the substituted text.
  • File Scope: Active from the point of definition to the end of the translation unit or until #undef.
  • No Semicolon in Definition: Adding ; to the replacement text often breaks control flow or expressions.
  • Argument Substitution: Parameters are replaced literally. No evaluation or type conversion occurs before substitution.
  • Reserved Identifiers: Identifiers starting with _ followed by uppercase letters or double underscores are reserved for the implementation.
  • Cannot Be Redefined: #define FOO 1 followed by #define FOO 2 triggers a warning/error unless the replacement text is identical. Use #undef first.

Best Practices

  1. Parenthesize Everything: #define MUL(a,b) ((a) * (b)) prevents operator precedence bugs.
  2. Use do { ... } while(0) for Multi-Statement Macros: Ensures correct parsing in if/else blocks without requiring trailing semicolons to break syntax.
  3. Prefer Standard C Features: Use const, enum, and static inline functions for type-safe, debuggable alternatives.
  4. Name in ALL_CAPS: Clearly distinguishes macros from variables and functions.
  5. Avoid Side Effects in Arguments: SQUARE(i++) expands to (i++) * (i++) → undefined behavior.
  6. Document Complex Macros: Explain expected arguments, expansion behavior, and known limitations.
  7. Guard Against Re-inclusion: Use macros as include guards (#ifndef HEADER_H, #define HEADER_H, #endif) or #pragma once.

Common Pitfalls

  • 🔴 Operator Precedence Failure: #define SQUARE(x) x * xSQUARE(1+2) expands to 1+2*1+2 = 5, not 9.
  • 🔴 Double Evaluation: Function-like macros evaluate arguments multiple times. Breaks with ++, --, or volatile expressions.
  • 🔴 Trailing Semicolon Issues: #define RETURN(x) return x;if(cond) RETURN(1) else RETURN(0); fails to compile.
  • 🔴 Namespace Pollution: Global macros override identifiers in any included header or source file.
  • 🔴 Debugging Difficulty: Compilers see expanded code, not macro names. Use gcc -E to inspect preprocessor output.
  • 🔴 String Literal Concatenation Confusion: #define MSG "Hello" " World" works, but #define MSG(x) "Value: " #x requires careful spacing.

Predefined Macros

Standard C compilers automatically define these read-only macros:

MacroMeaning
__FILE__Current source file name (string)
__LINE__Current line number (integer)
__DATE__Compilation date (e.g., "May 01 2026")
__TIME__Compilation time (e.g., "14:30:00")
__func__Current function name (string, C99)
__STDC__Defined as 1 in strictly conforming C implementations
__STDC_VERSION__C standard version (e.g., 201112L for C11, 202311L for C23)

Modern Alternatives & Migration Guide

Macro Use CaseModern C Replacement
Constantsconst type name = value; or enum { NAME = value };
Inline Calculationsstatic inline type func(params) { ... }
Type Selection_Generic (C11) for compile-time type dispatch
Assertions_Static_assert (C11) for compile-time validation
Debug PrintsInline functions with __func__, __FILE__, __LINE__

Macros remain necessary for include guards, conditional compilation (#ifdef), and low-level metaprogramming, but modern C encourages minimizing their use in favor of type-safe language features.

Standards & Compiler Behavior

  • C89/C90: Core #define, #undef, #, ## standardized.
  • C99: Added __func__, variadic macros (#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)).
  • C11/C17/C23: Enhanced _Generic, improved predefined macro values, and stricter expansion rules.
  • Diagnostics: Use gcc -E or clang -E to output preprocessed source. Warnings like -Wundef and -Wmacro-redefined catch common issues.

1. C srand() Function – Understanding Seed Initialization

https://macronepal.com/aws/understanding-the-c-srand-function

Explanation:
This article explains how the srand() function is used in C to initialize the pseudo-random number generator. In C, random numbers generated by rand() are not truly random—they follow a predictable sequence. srand() sets the starting “seed” value for that sequence. If you use the same seed, you will always get the same sequence of numbers. Developers often use time(NULL) as the seed to ensure different results each time the program runs.


2. C rand() Function Mechanics and Limitations

https://macronepal.com/aws/c-rand-function-mechanics-and-limitations

Explanation:
This article describes how the rand() function generates pseudo-random numbers in C. It returns values between 0 and RAND_MAX. The function is deterministic, meaning it produces the same sequence unless the seed is changed using srand(). It also highlights limitations such as poor randomness quality, predictability, and why rand() is not suitable for cryptographic or security-critical applications.


3. C log() Function

https://macronepal.com/aws/c-log-function-2

Explanation:
This guide covers the log() function in C, which calculates the natural logarithm (base e) of a number. It belongs to the <math.h> library. The article explains syntax, usage, and examples, showing how log(x) is used in scientific computing, mathematics, and engineering applications. It also discusses domain restrictions (input must be positive).


4. Mastering Date and Time in C

https://macronepal.com/aws/mastering-date-and-time-in-c

Explanation:
This article explains how C handles date and time using the <time.h> library. It covers functions like time(), clock(), difftime(), and structures such as struct tm. It also shows how to format and manipulate time values, making it useful for logging events, measuring program execution, and working with timestamps.


5. Mastering time_t Type in C

https://macronepal.com/aws/mastering-the-c-time_t-type-for-time-management

Explanation:
This article focuses on the time_t data type, which represents time in C as seconds since the Unix epoch (January 1, 1970). It explains how time_t is used with functions like time() to get current system time. It also shows conversions between time_t and readable formats using localtime() and gmtime().


6. C exp() Function Mechanics and Implementation

https://macronepal.com/aws/c-exp-function-mechanics-and-implementation

Explanation:
This article explains the exp() function in C, which computes (Euler’s number raised to a power). It is part of <math.h> and is widely used in exponential growth/decay problems, physics, finance, and machine learning. The article also discusses how the function is implemented internally and its numerical behavior.


7. C log() Function (Alternate Guide)

https://macronepal.com/aws/c-log-function

Explanation:
This is another guide on the log() function, reinforcing how natural logarithms work in C. It compares log() with log10() and shows when to use each. It also includes practical examples for mathematical calculations and real-world scientific usage.


8. Mastering log10() Function in C

https://macronepal.com/aws/mastering-the-log10-function-in-c

Explanation:
This article explains the log10() function, which calculates logarithm base 10. It is commonly used in engineering, signal processing, and scientific notation conversions. The guide shows syntax, examples, and differences between log() (natural log) and log10().


9. Understanding the C tan() Function

https://macronepal.com/aws/understanding-the-c-tan-function

Explanation:
This article explains the tan() function in <math.h>, which computes the tangent of an angle (in radians). It includes usage examples, mathematical background, and notes about input constraints (such as undefined values at certain angles like π/2).


10. Mastering Random Numbers in C (Secure vs Predictable)

https://macronepal.com/aws/mastering-c-random-numbers-for-secure-and-predictable-applications

Explanation:
This guide explains how random number generation works in C, including differences between predictable pseudo-random generators (rand()) and more secure or system-based randomness methods. It also discusses when randomness matters (games, simulations vs cryptography) and why rand() is not secure.


11. Free Online C Code Compiler

https://macronepal.com/aws/free-online-c-code-compiler-2

Explanation:
This article introduces an online C compiler that allows you to write, compile, and run C programs directly in the browser. It is useful for beginners who don’t want to install GCC or set up a local development environment. It supports quick testing of C code snippets.

Leave a Reply

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


Macro Nepal Helper