C++11 中采用的 C99 预处理器功能 (C++11)

在 C++11 标准中,采用了若干 C99 预处理器功能部件为 C 和 C++ 编译器提供公共预处理器接口。 这样可以将 C 源文件移植到 C++ 编译器,并消除旧的 C 和 C++ 预处理器之间存在的一些细微语义差异,从而避免预处理器兼容性问题或分散预处理器行为。

具有扩展整数类型的预处理器算术

在 C89, C++98和 C++03 预处理器中,类型为 intunsigned int 的整数字面值将扩展为 longunsigned long。 但是,在 C99 和 C++11 预处理器中,在 XL C/C++中的正常情况下,所有 signedunsigned 整数类型 (包括字符类型) 都将加宽到 long longunsigned long long

如果启用了此功能,并且-q32-q64 方式设置了 -qnolonglong-qlanglvl=noc99longlong ,那么预处理器仍对预处理器控制表达式中的所有整数和字符文字使用 long longunsigned long long 表示法。

以下示例在 -q32 方式下的 AIX® 平台 上有效,其中底层类型为wchar_t是无符号短整型。
#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 
以下示例显示了在 -q32 方式下启用 long long 支持的情况,此功能会导致在 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

如果禁用了此功能并且设置了 -qwarn0x ,那么 C++11 预处理器会对 #if#elif 伪指令中的控制表达式进行求值,并将求值结果与 non-C++11 预处理器的求值结果进行比较。 如果它们不同,那么编译器会警告您预处理器控制表达式在 C++11 和 non-C++11 语言级别之间的求值方式不同。

混合字符串字面值并置

常规字符串可与宽字符串字面值并置,例如:
#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!");
}
此示例在执行时打印以下输出:
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: 1540-0893 (W) The header file name "0x/mylib.h" 
in #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 -qnodollar, '$' 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 ); 
在启用此功能并指定了 -qnodollar 的情况下编译或预处理此示例时,编译器将发出以下警告消息:
"w.C", line 1.10: 1540-0891 (W) Missing white space between 
the identifier "A" and the replacement list.

_Pragma 运算符

_Pragma 运算符是指定 #pragma 伪指令的替代方法。 例如,以下两个语句等效:
#pragma comment(copyright, "IBM 2010")
_Pragma("comment(copyright, \"IBM 2010\")")
编译以下代码时,会将字符串 IBM 2010 插入到 C++ 对象文件中:
_Pragma("comment(copyright, \"IBM 2010\")")
int main() 
{
   return 0;
}

变量宏和空宏自变量

C99 和 C++11中支持可变宏和空宏参数。 有关详细信息,请参阅 可变宏

预定义的宏

__STDC_HOSTED__ 宏预定义为 1 ,无论是否定义了以下宏:
  • __STDC__
  • __STDC_VERSION__
  • __STDC_ISO_10646_