C99 preprocessor features adopted in C++11 (C++11)
In the C++11 standard, several C99 preprocessor features are adopted to provide a common preprocessor interface for C and C++ compilers. This eases porting C source files to the C++ compiler and eliminates some subtle semantic differences that exist between the old C and C++ preprocessors, thus avoiding preprocessor compatibility issues or diverging preprocessor behaviors.
- Preprocessor arithmetic with extended integer types
- Mixed string literal concatenation
- Diagnostic for header files and include names
- Increased limit for
#linedirectives - Diagnostic for object-like macro definitions
- The
_Pragmaoperator - Variadic macros and empty macro arguments
Preprocessor arithmetic with extended integer types
In the C89, C++98, and C++03 preprocessors, integer literals that have
int or unsigned int type are widened to long or
unsigned long. However, in the C99 and C++11 preprocessors, all
signed and unsigned integer types (character types included) are
widened to long long or unsigned long long under normal
circumstances in ILE C/C++.
OPTION(*NOLONGLONG) is set, the preprocessor
still uses long long or unsigned long long representations for all
integral and character literals in preprocessor controlling expressions. The following example
illustrates the case that wchar_t, whose underlying type is unsigned
short or unsigned int, depending on LOCALETYPE, is
widened to unsigned long
long.#if L'\x0' - L'\x1' < 0
#error non-C++11 preprocessor arithmetic.
#else
#error C++11 preprocessor arithmetic! L'\x0' and L'\x1' are widened to \
unsigned long long
#endif#if ~0ull == 0u + ~0u
#error C++11 preprocessor arithmetic! 0u has the same representation as 0ull, \
hence ~0ull == 0u + ~0u
#else
#error non-C++11 preprocessor arithmetic. 0ul does not have the same representation as 0ull,\
hence ~0ull != 0u + ~0u
#endifMixed string literal concatenation
#include <wchar.h>
#include <stdio.h>
int main()
{
wprintf(L"Guess what? %ls\n", "I can now concate" L"nate regular strings\
and wide strings!");
printf("Guess what? %ls\n", L"I can now concate" "nate strings\
this way too!");
return 0;
}Guess what? I can now concatenate regular strings and wide strings!
Guess what? I can now concatenate strings this way too!Diagnostic for header files and include names
#include directive is a digit, the
compiler issues a warning message. Consider the following example://inc.C
#include "0x/mylib.h"
int main()
{
return 0;
}"inc.C", line 1.10: CZP0893(10) The header file name "0x/mylib.h" in the #include directive shall not start with a digit.Increased limit for #line directives
#line <integer> preprocessor directives
has been increased from 32,767 to 2,147,483,647 for the C++11 preprocessor in conformance with the
C99
preprocessor.#line 1000000 //Valid in C++11, but invalid in C++98
int main()
{
return 0;
}Diagnostic for object-like macro definitions
//w.C
//With LANGLVL(*EXTENDED0X), '$' is not part of the macro name,
//thus it begins the replacement list
#define A$B c
#define STR2( x ) # x
#define STR( x ) STR2( x )
char x[] = STR( A$B );"w.C", line 1.10: CZP0891(10) Missing white space between the identifier "A" and the replacement list.The _Pragma operator
_Pragma operator is an alternative method
of specifying #pragma directives. For example, the
following two statements are equivalent:#pragma comment(copyright, "IBM 2013")
_Pragma("comment(copyright, \"IBM 2013\")")_Pragma("comment(copyright, \"IBM 2013\")")
int main()
{
return 0;
}Variadic macros and empty macro arguments
__VA_ARGS__ to a user-defined identifier. Consider the following
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));