Before the MSVC compiler translates your C source into machine code, a distinct processing stage called the preprocessor runs first. The preprocessor performs textual transformations on the source file: it expands macros, inserts the contents of included header files, conditionally includes or excludes blocks of code, and handles several other directives that begin with aDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/MicrosoftDocs/cpp-docs/llms.txt
Use this file to discover all available pages before exploring further.
# character. Understanding the preprocessor and when it runs is fundamental to writing robust, maintainable C programs in Visual Studio.
Role of the Preprocessor in the Build Pipeline
The build of a single translation unit (a.c file) proceeds in the following stages:
Preprocessor directives are processed before macro expansion of surrounding code. This means a macro cannot expand into a preprocessor directive and have it recognized. For example, you cannot generate a
#include path dynamically through macro substitution in the standard way.Traditional vs. Conformant Preprocessor
MSVC ships two preprocessor implementations:| Mode | Enabled By | Description |
|---|---|---|
| Traditional | Default (before VS 2019 16.5) | Legacy behavior; some edge cases differ from the standard |
| Conformant | /Zc:preprocessor | Fully conformant C11/C17 preprocessor |
/Zc:preprocessor) is automatically activated when you compile with /std:c11 or /std:c17. It resolves many long-standing edge cases, particularly around variadic macro expansion, token pasting, and rescanning behavior.
Preprocessing Directives
The preprocessor recognizes the following directives. Each directive begins with a# as the first non-whitespace character on the line:
File Inclusion — #include
File Inclusion — #include
The For the full reference on search order and nested includes, see Preprocessor Directives.
#include directive inserts the contents of another file at the point where it appears. Two forms are supported:- Angle-bracket form
<file>— searches the system include directories (set by/IandINCLUDEenvironment variable). - Quoted form
"file"— searches first in the directory of the including file, then falls back to the system search path.
Macro Definition — #define and #undef
Macro Definition — #define and #undef
#define creates object-like macros (simple substitution) and function-like macros (parameterized substitution). #undef removes a macro definition so it can be redefined.Conditional Compilation — #if / #ifdef / #ifndef / #elif / #else / #endif
Conditional Compilation — #if / #ifdef / #ifndef / #elif / #else / #endif
Conditional directives let you include or exclude sections of code based on compile-time expressions or macro definitions. These are the cornerstone of platform-specific and configuration-driven code.
Diagnostics — #error and #warning
Diagnostics — #error and #warning
#error emits a compile-time error and halts translation. #warning emits a non-fatal diagnostic message. Both are commonly used to enforce build prerequisites:Line Control — #line
Line Control — #line
#line overrides the compiler’s reported line number and optionally the filename used in diagnostics. It is primarily inserted by code generators (e.g., parser generators, IDL compilers) so that error messages point to the original source:Pragmas — #pragma
Pragmas — #pragma
#pragma passes implementation-specific instructions to the compiler. MSVC supports dozens of pragmas covering optimization, struct alignment, warning control, header-include guards, and linker directives. See the full Pragma Directives Reference for details.Predefined Macros
MSVC defines a rich set of macros automatically, without any#define directive in your source. These include:
Inspecting Preprocessor Output
You can view the output of the preprocessor without compiling by passing/P (preprocess to file) or /EP (preprocess to stdout) to the compiler:
Full Preprocessor Reference
The preprocessor is a large topic. This page provides an overview of its place in the build process. For detailed coverage of each directive, macro operator, and pragma, see:- Preprocessor Directives —
#include,#define,#undef,#if,#error,#line,#pragma - Macros (C/C++) — Object macros, function macros, token-pasting, stringizing,
__VA_ARGS__, predefined macros - Pragma Directives —
#pragma once,#pragma comment,#pragma warning,#pragma pack, and more