C90为预处理指令家族带来一位新成员:#pragma。通常状况下,你们不多见到它。函数
#pragma的做用是为特定的编译器提供特定的编译指示,这些指示是具体针对某一种(或某一些)编译器的,其余编译器可能不知道该指示的含义又或者对该指示有不一样的理解,也便是说,#pragma的实现是与具体平台相关的。
为了让你们了解#pragma的用法,这里暂时以HP C Compiler为例子。HP C编译器主要运行在HP-UX平台上,它的通常用法和gcc大体相同,例如要编译程序:
$cc example.c
若是咱们明确指示编译器优化代码,能够这样编译:
$cc +On example.c
其中n能够是一、二、三、4,分别表明不一样程度的优化,例如:
$cc +O2 example.c
这条命令指示HP C编译器对整个example.c的代码采起第2级别的优化编译。
可是,某种状况下咱们可能须要特殊对待某一部分的代码,譬如暂停优化,HP C编译器提供几种途径去实现,其中之一是使用#pragma:
//prog.c
void f(){...}
#pragma OPTIMIZE OFF
int g(){...}
#pragma OPTIMIZE ON
double h(){...}
$cc +O2 prog.c
上面的prog.c中有3个函数,咱们想用第2级别的优化编译代码整个文件。唯独函数g()例外,咱们出于某种考虑决定不对它进行任何优化,能够看到,用两条#pragma指令就可以达到目的。
第一条#pragma指令指示编译器中止优化代码,因而g()的代码是没有通过优化的。第二条#pragma指令通知编译器从新开始代码的优化编译(优化级别仍然是先前命令行给出的level 2),因此从h() 开始的代码又都是通过优化的。
这里以代码的优化编译为例简单介绍了#pragma的用法,读者必须记住:具体的#pragma指令在不一样状况下可能有不一样的效果。假设有两家厂商各自推出本身的C编译器,可能真会这么巧同时使用相同的#pragma指令,恰恰它们的实现又不相同,这样编译的代码就可能会出现意想不到的结果。因此,为了保证#pragma指令可以被正确的解释,咱们一般须要利用其余的预处理指令给予配合,例如:
...
#ifdef __hpux
#pragma FLOAT_TRAPS_ON _ALL
#endif
...
上例中,只有定义“__hpux”宏的HP C编译器才会看到#pragma指令,其余编译器,例如gcc,根本不会看到它的,由于gcc不会去定义“__hpux”宏,因此早在预处理阶段,#pragma指令的内容就被预处理程序删掉了。
有人可能会问:若是万一编译器看到它不认识的#pragma指令会报错吗?
答案是:不会。
具体到某一条#pragma指令的涵义不是C标准的管辖范围,编译器不可以由于看到不认识的#pragma指令就说程序有错,唯一的作法是忽略它。
例如:
/*Example C code*/
#pragma UNKNOWN_DIRECTIVE UNKNOWN_OPTION
int main(void)
{
return 0;
}
$gcc test.c
$./a.out
$
尽管gcc不认识上面代码中的#pragma指令,但编译test.c是彻底没有问题的。
如今,C99提供新的关键字“_Pragma”完成相似的功能,例如:
#pragma OPTIMIZE OFF
在C99中能够写成:
_Pragma(“OPTIMIZE OFF”) //注意:语句后面是没有分号的
“_Pragma”比“#pragma”(在设计上)更加合理,于是功能也有所加强。
例如,咱们的编译器支持4个不一样程度的优化等级,若是使用#pragma,则这样写:
#pragma OPT_LEVEL n //1≤n≤4
你会不会以为每次都要重复写“#pragma...”很麻烦?若是能够利用宏定义来简化书写就行了:
#define OPT_L(x) #pragma OPT_LEVEL x
这时咱们只须写:
OPT_L(3)
就至关于写:
#pragma OPT_LEVEL 3
惋惜,在C90里这永远是一个梦想!由于字符“#”在预处理指令中有特殊的用途,跟在它后面的必须是宏的参数名,例如:
#define MACRO(x) #x
那么,MACRO(example)的替换结果为:
“example”
能够想象,前面经过#define来定义一个关于#pragma的宏是不可行的。
不过,新的关键字“_Pragma”就很好的解决了问题,因为_Pragma并不能有字符“#”,因此咱们能够放心的定义宏:
#define OPT_L(X) PRAGMA(OPT_LEVEL X)
#define PRAGMA(X) _Pragma(#X)
这时,咱们只要写:
OPT_L(2)
通过预处理后,就成为:
_Pragma(“OPT_LEVEL 2”)
即:
#pragma OPT_LEVEL 2