The C preprocessor is attached to C, but it has a completely different syntax from the main language:
syntactically significant whitespace (end of line terminates a statement, gap after the macro determines the start of the replacement list)
keyword-based blocks instead of braced blocks,
elif
instead ofelse if
keyword-led definitions instead of declaration-reflects-use, no
=
for value definitionhints of an alternative string syntax (
#include <>
vs#include ""
)lazy evaluation (of C, obviously; but 6.10.3.1 can be read as implying a specific order of macro expansion as well, in the few places that matters)
It really doesn't look like C at all! Technically it is its own language, but it's always been used as a nearly-integral part of C and it seems very strange that it wouldn't integrate with it syntactically.
Wikipedia doesn't talk about its history; the Portland Pattern Repository gives it a passing mention, but doesn't go into detail beyond the fact that it was designed by other people than the rest of C. Dennis Ritchie's website with the history of C probably had the answer, but is unfortunately no longer available.
As a macro engine, it obviously has very different semantics from the runtime language, which would explain some differences, but not the visual design aspects (it's also unclear to modern eyes whether it was originally intended as being capable of the kind of fun that its replacement system allows, or whether it was "just" an expedient way to inline functions in a time before powerful optimizers). It feels like something closer to what eventually became C++ templates would have been a more logical evolution towards macros, if C-like semantics had actually been the starting point, but there's less concrete evidence of this than there is for the syntax.
Do we have any record of why it was designed this way, or what the creators' influences were?