Textový makroprocesor předzpracovává zdrojový text programu a předává ho dalším částem kompilátoru. Kromě náhrady identifikátorů řetězci a vkládání souborů (odst. 5.1.7), umožňuje definovat a využívat makra a podmíněný překlad. Jeho činnost je řízena příkazy, které jsou vyznačeny znakem # v první pozici řádku. Mezi tímto znakem a vlastním příkazem může být libovolný počet mezer (a tabulátorů).
Formát příkazů makroprocesoru nezávisí na jazyku C. Příkazy se mohou objevit na libovolném místě programu a platí do konce zdrojového souboru nebo do příkazu makroprocesoru, který ruší jejich význam.
S touto náhradou jsme se již seznámili v odst. 5.1.7. Má tvar
#define identifikátor řetězec
#undefine identifikátor
Případný středník je součástí řetězce (neukončuje příkaz!). Příkazy #define s prázdným řetězcem, např.
#define DEBUG #define VAX
Často používanou konstrukcí je definice konstant
#define BLOKSIZE 512 #define BITSOFCHAR 8 #define BITSOFINT (sizeof(int) * BITSOFCHAR
#define INC ++ #define EQUALS == #define THEN
if(x EQUALS y)THEN INC x; ...
if(x == y) ++x; ...
Příkaz #define zajistí náhradu identifikátoru řetězcem. Zobecněním tohoto principu je makro, kdy dochází k záměně několika identifikátorů současně. Příkazem
#define identifikátor-makro(formální parametry) řetězec
#define abs(x) (((x)<0)?-(x):(x))
z = abs(3*y-15);
z = (((3*y-15)<0)?-(3*y-15):(3*y-15));
Nyní je snad zřejmé, proč je vhodné v definičním řetězci používat hojně závorek. Mechanismus makra připomíná mechanismus funkcí. Liší se v tom, že se přeloží na přímý kód s menší režií než volání funkce. Kolikrát je parametr použit v definičním řetězci, tolikrát se vyhodnocuje. Poslední příklad to ukazuje dostatečně zřetelně. Přesto se makra používají v knihovně standardních funkcí. Například funkce
isascii(c)
#define isascii(c) ((unsigned)(c)<=0177).
Podmíněný překlad je řízen příkazy #if, #else, #elif a #endif. Je tedy lépe strukturován než podmíněný příkaz jazyka C.
Podmínka testovaná v příkazu #if musí být konstantním výrazem (bez přetypování, sizeof a výčtových konstant). Vyhodnotí-li se jako nenulová, text následující za příkazem #if až do prvního výskytu příkazu #else, #elif nebo #endif se do programu zařadí, jinak ne. V podmínce se může vyskytnout podvýraz tvořený unárním operátorem defined a identifikátorem, např.
defined DEBUG
defined (DEBUG).
Takový výraz se vyhodnotí jako 1, je-li identifikátor definován, jinak jako nula. Příkaz
#ifdef DEBUG
#if defined (DEBUG),
#ifndef DEBUG
#if ! defined (DEBUG).
Místo příkazu #include (odst. 5.1.7) makroprocesor zařadí obsah souboru, jehož jméno je v příkazu uvedeno. Je-li jméno souboru uzavřeno do uvozovek, hledá se soubor nejprve v adresáři, v němž se nachází zdrojový program, a teprve potom ve standardních adresářích. Je-li v úhlových závorkách <, >, hledá se jen ve standardních adresářích. Standardní adresáře jsou většinou podadresáře /usr/include. Příkladem mohou být zápisy:
#include <stdio.h>
#include "KPOC.h"
Programy v jazyku C vznikají i jako produkty jiných programů, tzv. generátorů (např. lex, yacc apod.). Chybová hlášení kompilátoru C se vztahují k překládanému souboru a řádku v tomto souboru, nikoliv k původnímu zdrojovému souboru pro generátor. Příkazem
#line řádek "soubor"