preprocessing-file: group
group: group-part group group-part
group-part: control-line if-section text-line # conditionally-supported-directive
control-line: # include pp-tokens new-line # define identifier replacement-list new-line # define identifier lparen identifier-list ) replacement-list new-line # define identifier lparen ... ) replacement-list new-line # define identifier lparen identifier-list , ... ) replacement-list new-line # undef identifier new-line # line pp-tokens new-line # error pp-tokens new-line # pragma pp-tokens new-line # new-line
if-section: if-group elif-groups else-group endif-line
if-group: # if constant-expression new-line group # ifdef identifier new-line group # ifndef identifier new-line group
elif-groups: elif-group elif-groups elif-group
elif-group: # elif constant-expression new-line group
else-group: # else new-line group
endif-line: # endif new-line
text-line: pp-tokens new-line
conditionally-supported-directive: pp-tokens new-line
lparen: a ( character not immediately preceded by white-space
identifier-list: identifier identifier-list , identifier
replacement-list: pp-tokens
pp-tokens: preprocessing-token pp-tokens preprocessing-token
new-line: the new-line character
defined-macro-expression: defined identifier defined ( identifier )
h-preprocessing-token: any preprocessing-token other than >
h-pp-tokens: h-preprocessing-token h-pp-tokens h-preprocessing-token
has-include-expression: __has_include ( < h-char-sequence > ) __has_include ( " q-char-sequence " ) __has_include ( string-literal ) __has_include ( < h-pp-tokens > )
has-attribute-expression: __has_cpp_attribute ( pp-tokens )
Attribute | Value |
assert | 201806L |
carries_depencency | 200809L |
deprecated | 201309L |
ensures | 201806L |
expects | 201806L |
fallthrough | 201603L |
likely | 201803L |
maybe_unused | 201603L |
no_unique_address | 201803L |
nodiscard | 201603L |
noreturn | 200809L |
unlikely | 201803L |
# if constant-expression new-line group # elif constant-expression new-line groupcheck whether the controlling constant expression evaluates to nonzero.
#if 'z' - 'a' == 25 if ('z' - 'a' == 25)
# ifdef identifier new-line group # ifndef identifier new-line groupcheck whether the identifier is or is not currently defined as a macro name.
#if __has_include(<optional>) # include <optional> # if __cpp_lib_optional >= 201603 # define have_optional 1 # endif #elif __has_include(<experimental/optional>) # include <experimental/optional> # if __cpp_lib_experimental_optional >= 201411 # define have_optional 1 # define experimental_optional 1 # endif #endif #ifndef have_optional # define have_optional 0 #endif— end example
#if __has_cpp_attribute(acme::deprecated) # define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]] #else # define ATTR_DEPRECATED(msg) [[deprecated(msg)]] #endif ATTR_DEPRECATED("This function is deprecated") void anvil();— end example
# include < h-char-sequence > new-line
# include " q-char-sequence " new-linecauses the replacement of that directive by the entire contents of the source file identified by the specified sequence between the " delimiters.
# include < h-char-sequence > new-linewith the identical contained sequence (including > characters, if any) from the original directive.
# include pp-tokens new-line
#include <stdio.h> #include <unistd.h> #include "usefullib.h" #include "myprog.h"— end note
#if VERSION == 1
#define INCFILE "vers1.h"
#elif VERSION == 2
#define INCFILE "vers2.h" // and so on
#else
#define INCFILE "versN.h"
#endif
#include INCFILE
— end example# define identifier replacement-list new-line
# define identifier lparen identifier-list ) replacement-list new-line # define identifier lparen ... ) replacement-list new-line # define identifier lparen identifier-list , ... ) replacement-list new-linedefines a function-like macro with parameters, whose use is similar syntactically to a function call.
#define LPAREN() (
#define G(Q) 42
#define F(R, X, ...) __VA_OPT__(G R X) )
int x = F(LPAREN(), 0, <:-); // replaced by int x = 42;
— end example#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) #define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) #define EMP F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) F(EMP) // replaced by f(0) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 }; #define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // ill-formed: ## may not appear at // the beginning of a replacement list ([cpp.concat]) #define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ H2(a, b, c, d) // replaced by ab, c, d #define H3(X, ...) #__VA_OPT__(X##X X##X) H3(, 0) // replaced by "" #define H4(X, ...) __VA_OPT__(a X ## X) ## b H4(, 1) // replaced by a b #define H5A(...) __VA_OPT__()/**/__VA_OPT__() #define H5B(X) a ## X ## b #define H5C(X) H5B(X) H5C(H5A()) // replaced by ab— end example
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
char p[] = join(x, y); // equivalent to char p[] = "x ## y";
join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y) "x ## y"
# undef identifier new-line
#define TABSIZE 100 int table[TABSIZE];
#define max(a, b) ((a) > (b) ? (a) : (b))
#define x 3 #define f(a) f(x * (a)) #undef x #define x 2 #define g f #define z z[0] #define h g(~ #define m(a) a(w) #define w 0,1 #define t(a) a #define p() int #define q(x) x #define r(x,y) x ## y #define str(x) # x f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); g(x+(3,4)-w) | h 5) & m (f)^m(m); p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; char c[2][6] = { str(hello), str() };
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); int i[] = { 1, 23, 4, 5, }; char c[2][6] = { "hello", "" };— end example
#define str(s) # s
#define xstr(s) str(s)
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
x ## s, x ## t)
#define INCFILE(n) vers ## n
#define glue(a, b) a ## b
#define xglue(a, b) glue(a, b)
#define HIGHLOW "hello"
#define LOW LOW ", world"
debug(1, 2);
fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away
== 0) str(: @\n), s);
#include xstr(INCFILE(2).h)
glue(HIGH, LOW);
xglue(HIGH, LOW)
printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);
#include "vers2.h" (after macro replacement, before file access)
"hello";
"hello" ", world"
printf("x1= %d, x2= %s", x1, x2);
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s);
#include "vers2.h" (after macro replacement, before file access)
"hello";
"hello, world"
— end example#define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };
int j[] = { 123, 45, 67, 89, 10, 11, 12, };— end example
#define OBJ_LIKE (1-1) #define OBJ_LIKE /* white space */ (1-1) /* other */ #define FUNC_LIKE(a) ( a ) #define FUNC_LIKE( a )( /* note the white space */ \ a /* other stuff on this line */ )
#define OBJ_LIKE (0) // different token sequence #define OBJ_LIKE (1 - 1) // different white space #define FUNC_LIKE(b) ( a ) // different parameter usage #define FUNC_LIKE(b) ( b ) // different parameter spelling— end example
#define debug(...) fprintf(stderr, __VA_ARGS__) #define showlist(...) puts(#__VA_ARGS__) #define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__)) debug("Flag"); debug("X = %d\n", x); showlist(The first, second, and third items.); report(x>y, "x is %d but y is %d", x, y);
fprintf(stderr, "Flag"); fprintf(stderr, "X = %d\n", x); puts("The first, second, and third items."); ((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));— end example
# line digit-sequence new-line
# line digit-sequence " s-char-sequence " new-line
# line pp-tokens new-line
# pragma pp-tokens new-line
Macro name | Value |
201603L | |
201304L | |
200704L | |
201606L | |
200809L | |
201304L | |
201603L | |
201603L | |
200707L | |
201304L | |
201703L | |
200604L | |
201411L | |
201806L | |
201603L | |
201304L | |
201606L | |
201603L | |
201606L | |
201511L | |
201304L | |
200806L | |
201606L | |
200907L | |
201411L | |
201510L | |
201411L | |
201606L | |
201806L | |
200809L | |
201603L | |
200710L | |
200710L | |
201304L | |
200610L | |
201309L | |
201411L | |
201606L | |
201611L | |
200806L | |
200704L | |
200710L | |
200809L | |
201304L | |
200704L | |
201611L |
_Pragma ( string-literal )
#pragma listing on "..\listing.dir"
_Pragma ( "listing on \"..\\listing.dir\"" )The latter form is processed in the same way whether it appears literally as shown, or results from macro replacement, as in:
#define LISTING(x) PRAGMA(listing on #x) #define PRAGMA(x) _Pragma(#x) LISTING( ..\listing.dir )