Created: 2023-08-16 17:02
Status: #concept
Subject: Programming
Tags: C Constant Expression Preprocessor

Macro Definition

In C, we can use the #define Directive to declare Constant value aliases.

  • we can also use them to make Macro Functions.
  • they have like Global Scope variables until the end of the program's lifetime.

Syntax

In the background the Preprocessor will find all CONSTANT_NAME strings in your code and replace them with <constant value> before Compiling the program.

#define INCHES_PER_POUND 166
/* we have to use parenthesis () when our expression has operators */
#define RECIPROCAL_OF_PI (1.0f / 3.14159f)
/* it's like variable assignment, but with #define at the start & no = sign & ; */

weight = (volume + INCHES_PER_POUND - 1) / INCHES_PER_POUND;
/* will become */
weight = (volume + 166 - 1) / 166;

Common Pitfall: Not Adding () Around Replacement List

Whenever we have parameters in our macros or Expressions in our replacement-list, we must enclose them in () to ensure they behave correctly.

  • we do this because the preprocessor simply replaces the text of our code before Compiling.

Macro Definition Replacement List Parenthesis.png

Parameterized Macros (function-like Macros)

#define MAX(x,y)    ((x) > (y) ? (x) : (y))
#define IS_EVEN(n)  ((n) % 2 == 0)

Stringization Operator #

When using a parameterized macro with an argument x, using #x in the replacement-list it encloses the string representation as a String Literal"x".

#include <stdio.h>

#define MAX(x,y) (x > y ? printf(#x " is greater.") : printf(#y " is greater."))

int main(void)
{
    MAX(2/2, 6/2);
}

// outputs: 6/2 is greater.

Token Pasting Operator ##

We can easily make new identifiers with these macros.

#define MK_ID(n) i##n

int MK_ID(1), MK_ID(2), MK_ID(3);
// is preprocessed into this
int i1, i2, i3;

References