C99 C++11 中采用的预处理器功能部件 (C++11)
注: IBM® 支持 C++11的选定功能,在批准之前称为 C++0x 。 IBM 将继续开发和实施此标准的功能部件。 语言级别的实现基于 IBM对此标准的解释。 在完成 IBM对所有 C++11 功能部件的实现 (包括对新的 C++ 标准库的支持) 之前,该实现可能会从发行版更改为发行版。 IBM 不会尝试在源代码,二进制或列表以及其他编译器接口中维护与 IBM先前发行版的新 C++11 功能部件实现的兼容性,因此不应将其作为稳定的编程接口。
在 C++11 标准中,采用了若干 C99 预处理器功能部件为 C 和 C++ 编译器提供公共预处理器接口。 这可以将 C 源文件移植到 C++ 编译器,并消除旧的 C 和 C++ 预处理器之间存在的一些细微语义差异,从而避免预处理器兼容性问题或分散预处理器行为。
C++11: 中采用了以下 C99 预处理器功能部件
- 具有扩展整数类型的预处理器算术
- 混合字符串字面值并置
- 头文件和包含名称的诊断
- 增加了
#line伪指令的限制 - 对象类宏定义的诊断
_Pragma操作程序- 变量宏和空宏自变量
具有扩展整数类型的预处理器算术
在 C89, C++98和 C++03 预处理器中,类型为 int 或 unsigned int 的整数字面值将扩展为 long 或 unsigned long。 但是,在 C99 和 C++11 预处理器中,在 ILE C/C + + 的正常情况下,所有 signed 和 unsigned 整数类型 (包括字符类型) 都将扩展为 long long 或 unsigned long long 。
如果启用了此功能,并且设置了
OPTION(*NOLONGLONG) ,那么预处理器仍对预处理器控制表达式中的所有整数和字符文字使用 long long 或 unsigned long long 表示法。 以下示例说明了 wchar_t(其底层类型为 unsigned
short 或 unsigned int,具体取决于 LOCALETYPE) 被拉大到 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以下示例显示了启用长整型支持的情况,此功能会导致在 non-C++11 预处理器和 C++11 预处理器之间选择不同的包含分支。
#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
#endif混合字符串字面值并置
常规字符串可以与宽字符串字面值并置,例如:
#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!诊断头文件和包含名称
启用此功能后,如果
#include 伪指令中头文件名的第一个字符是数字,那么编译器将发出警告消息。 考虑下列出例://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.增加了 #line 伪指令的限制
对于符合 C99 预处理器的 C++11 预处理器,
#line <integer> 预处理器伪指令的上限已从 32,767 增加到 2,147,483,647。#line 1000000 //Valid in C++11, but invalid in C++98
int main()
{
return 0;
}诊断对象类宏定义
如果对象类宏名称与其在宏定义中的替换列表之间没有空格,那么 C++11 编译器将发出警告消息。 考虑下列出例:
//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._Pragma 运算符
_Pragma 运算符是指定 #pragma 伪指令的替代方法。 例如,以下两个语句等效:#pragma comment(copyright, "IBM 2013")
_Pragma("comment(copyright, \"IBM 2013\")")编译以下代码时,会将字符串 IBM 2013 插入到 C++ 对象文件中:
_Pragma("comment(copyright, \"IBM 2013\")")
int main()
{
return 0;
}变量宏和空宏自变量
在 C99 和 C++11中支持可变宏和空宏参数。 此功能部件支持将变量参数标识从
__VA_ARGS__ 重命名为用户定义的标识的机制。 考虑下列出例:#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));