每种C和C++的实现支持对其宿主机或操作系统唯一的功能。例如,一些程序需要精确控制超出数据所在的储存空间,或着控制特定函数接受参数的方式。#pragma指示使每个编译程序在保留C和C++语言的整体兼容性时提供不同机器和操作系统特定的功能。编译指示被定义为机器或操作系统特定的,并且通常每种编译程序是不同的。
语法:
#pragma token_string
“token_string”是一系列字符用来给出所需的特定编译程序指令和参数。数字符号“#”必须是包含编译指令的行中第一个非空白字符;而空白字符可以隔开数字符号“#”和关键字“pragma”。在#pragma后面,写任何翻译程序能够作为预处理符号分析的文本。#pragma的参数类似于宏扩展。
如果编译程序发现它不认得一个编译指示,它将给出一个警告,可是编译会继续下去。
为了提供新的预处理功能,或者为编译程序提供由实现定义的信息,编译指示可以用在一个条件语句内。C和C++编译程序可以识别下列编译程序指令。
alloc_text | comment | init_seg* | optimize |
auto_inline | component | inline_depth | pack |
bss_seg | data_seg | inline_recursion | pointers_to_members* |
check_stack | function | intrinsic | setlocale |
code_seg | hdrstop | message | vtordisp* |
const_seg | include_alias | once | warning |
*仅用于C++编译程序。
1 alloc_text
#pragma alloc_text( "textsection", function1, ... )
命名特别定义的函数驻留的代码段。该编译指示必须出现在函数说明符和函数定义之间。
alloc_text编译指示不处理C++成员函数或重载函数。它仅能应用在以C连接方式说明的函数——就是说,函数是用extern "C"连接指示符说明的。如果你试图将这个编译指示应用于一个具有C++连接方式的函数时,将出现一个编译程序错误。
由于不支持使用__based的函数地址,需要使用alloc_text编译指示来指定段位置。由textsection指定的名字应该由双引号括起来。
alloc_text编译指示必须出现在任何需要指定的函数说明之后,以及这些函数的定义之前。
在alloc_text编译指示中引用的函数必须和该编译指示处于同一个模块中。如果不这样做,使以后一个未定义的函数被编译到一个不同的代码段时,错误会也可能不会被捕获。即使程序一般会正常运行,但是函数不会分派到应该在的段。
alloc_text的其它限制如下:
它不能用在一个函数内部。
它必须用于函数说明以后,函数定义以前。
2 auto_inline
#pragma auto_inline( [{on | off}] )
当指定off时将任何一个可以被考虑为作为自动嵌入扩展候选的函数排除出该范围。为了使用auto_inline编译指示,将其紧接着写在一个函数定义之前或之后(不是在其内部)。该编译指示将在其出现以后的第一个函数定义开始起作用。auto_inline编译指示对显式的inline函数不起作用。
3 bss_seg
#pragma data_seg( ["section-name"[, "section-class"] ] )
为未初始化数据指定缺省段。data_seg编译指示除了工作于已初始化数据而不是未初始化的以外具有一样的效果。在一些情况下,你能使用bss_seg将所有未初始化数据安排在一个段中来加速你的装载时间。
#pragma bss_seg( "MY_DATA" )
将导致把#pragma语句之后的未初始化的数据安排在一个叫做MY_DATA的段中。
用bss_seg编译指示分配的数据不包含任何关于其位置的信息。
第二个参数section-class是用于兼容2.0版本以前的Visual C++的,现在将忽略它。
4 check_stack
#pragma check_stack([ {on | off}] )
#pragma check_stack{+ | –}
如果指定off(或者“-”)指示编译程序关闭堆栈探测,或者指定on(或“+”)打开堆栈探测。如果没有给出参数,堆栈探测将根据默认设置决定。该编译指示将在出现该指示之后的第一个函数开始生效。堆栈探测既不是宏和能够生成嵌入代码函数的一部分。
如果你没有给出check_stack编译指示的参数,堆栈检查将恢复到在命令行指定的行为。详细情况见编译程序参考。#pragma check_stack和/Gs选项的互相作用情况在表2.1中说明。
表 2.1 使用check_stack编译指示
编译指示 | 用/Gs选项编译? | 行为 |
#pragma check_stack()或#pragma check_stack | 是 | 后续的函数关闭堆栈检查 |
#pragma check_stack()或#pragma check_stack | 否 | 后续的函数打开堆栈检查 |
#pragma check_stack(on)或#pragma check_stack(+) | 是或者否 | 后续的函数打开堆栈检查 |
#pragma check_stack(off)或#pragma check_stack(-) | 是或者否 | 后续的函数关闭堆栈检查 |
5 code_seg
#pragma code_seg( ["section-name"[,"section-class"] ] )
指定分配函数的代码段。code_seg编译指示为函数指定默认的段。你也能够像段名一样指定一个可选的类名。使用没有段名字符串的#pragma code_seg将恢复分配到编译开始时候的状态。
6 const_seg
#pragma const_seg( ["section-name"[, "section-class"] ] )
指定用于常量数据的默认段。data_seg编译指示除了可以工作于所有数据以外具有一样的效果。你能够使用该编译指示将你的常量数据保存在一个只读的段中。
#pragma const_seg( "MY_DATA" )
导致在#pragma语句后面的常量数据分配在一个叫做MY_DATA的段中。
用const_seg编译指示分配的数据不包含任何关于其位置的信息。
第二个参数section-class是用于兼容2.0版本以前的Visual C++的,现在将忽略它。
7 comment
#pragma comment( comment-type [, commentstring] )
将描述记录安排到目标文件或可执行文件中去。comment-type是下面说明的五个预定义标识符中的一个,用来指定描述记录的类型。可选的commentstring是一个字符串文字值用于为一些描述类型提供附加的信息。因为commentstring是一个字符串文字值,所以它遵从字符串文字值的所有规则,例如换码字符、嵌入的引号(")和联接。
7-1 compiler
在目标文件中放置编译程序名和版本号。该描述记录被连接程序忽略。如果你为这个记录类型提供一个commentstring参数,编译程序将生成一个警告。
7-2 exestr
将commentstring放置到目标文件中去。在连结时,这个字符串再被放到可执行文件去中。当可执行文件被装载时这个字符串不会被装入内存,然而,它可以被一个能够在文件中搜索可打印字符串的程序找到。该描述记录的一个用处是在可执行文件中嵌入版本号或者类似的信息。
7-3 lib
将一个库搜索记录放置到目标文件中去。该描述类型必须有包含你要连接程序搜索的库名(和可能的路径)的commentstring参数。因为在目标文件中该库名先于默认的库搜索记录,所以连接程序将如同你在命令行输入这些库一样来搜索它们。你可以在一个源文件中放置多个库搜索记录,每个记录将按照它们出现在源文件中的顺序出现在目标文件中。
7-4 linker
在目标文件中放置连接程序选项。你可以用这个描述类型指定连接程序选项来代替在Project Setting对话框中Link页内的选项。例如,你可以指定/include选项以强迫包含一个符号:
#pragma comment(linker, "/include:__mySymbol")
7-5 user
在目标文件中包含一个普通描述记录。commentstring参数包含描述的文本。该描述记录将被连接程序忽略。
下面的编译指示导致连接程序在连接时搜索EMAPI.LIB库。连接程序首先在当前工作目录然后在LIB环境变量指定的路径中搜索。
#pragma comment( lib, "emapi" )
下面的编译指示导致编译程序将其名字和版本号放置到目标文件中去。
The following pragma causes the compiler to place the name and version number of the compiler in the object file:
#pragma comment( compiler )
注意,对于具有commentstring参数的描述记录,你可以使用其它用作字符串文字量的宏来提供宏扩展为字符串文字量。你也能够联结任何字符串文字量和宏的组合来扩展成为一个字符串文字量。例如,下面的语句是可以接受的:
#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ )