C99 preprocessor features adopted in C++0x
In the C++0x 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
#line
directives - Diagnostic for object-like macro definitions
- The
_Pragma
operator - 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++0x 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++0x preprocessor arithmetic.
#else
#error C++0x preprocessor arithmetic! L'\x0' and L'\x1' are widened to \
unsigned long long
#endif
#if ~0ull == 0u + ~0u
#error C++0x preprocessor arithmetic! 0u has the same representation as 0ull, \
hence ~0ull == 0u + ~0u
#else
#error non-C++0x preprocessor arithmetic. 0ul does not have the same representation as 0ull,\
hence ~0ull != 0u + ~0u
#endif
Mixed 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++0x preprocessor in conformance with the C99 preprocessor.#line 1000000 //Valid in C++0x, 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));