C和C++的每个实现对它的主机或操作系统都支持一些独有的特征。
例如,某些程序须对存放数据的存储器区域进行精确的控制,或必须控制特定函数接受参量的方式。
#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。
依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
语法
#pragma 语言符号字符串
语言符号字符串是给出特有编译器指令和参量的字符序列。
数字符号(#)必须是包含编译指示行中的第一个非空白字符。空白字符可分开数字符号(#)和单词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++编译器支持
--------------------------------------------------------------------------------
C++编译器专有编译指示
以下是C++编译器专有的编译指示指令:
init_seg
pointers_to_members
vtordisp
warning
init_seg
#pragma init-seg({complier/lib/user/ "section-name" [,"func-name"]})
该指令指定一个影响启动代码执行顺序的关键字或代码段。
由于全局静态对象的初始化可能涉及执行代码,因此必须指定创建对象时定义的一个关键字。
在动态连接库(DLL)或需初始化的库中使用init_seg编译指示尤其重要。
init_seg编译指示的选项如下:
complier
该选项保留给Microsoft C 运行库初始化。这个组中的对象最先被创建。lib用于第三方类库供应商的初始化。该组中的对象在complier标志之后,其他标记之前创建。
user
用于任何用户。此组对象最后创建。
section_name
允许初始化段的显示规格。在一个用户指定section-name(段名称)中的对象不能被隐含地创建,但它们的地址可放在以section_name命名的段中。
func_name
指定在程序退出时在exit()地方调用的函数。
指定的函数必须与exit函数具有相同的特征:int funcname(void(__cdecl*)(void));
如果你需要延迟初始化过程(例如,在一个DLL中),你可以选择显式地指定该段名称。然后必须为每个静态对象调用构造函数。
pointers_to_members
#progma pointers_to_members(指针说明,[最一般表示])
该指令指定一个类成员的指针能否在其相关定义之前被说明,且用于控制该指针尺寸和解释该指针需要的代码。
你可以把一个pointers_to_members编译指示放入你的源文件中替换/vmx编译器选项。
指针说明参量指定你在一个关联函数定义之前还是之后说明了一个成员的指针。指针说明参量是以下两个符号之一:
参量 说明
full_generality 生成安全、但常常并非最优的代码。如果在关联类定义之前说明任何成员的指针,可使用full_generality。该参量通常使用最一般表示参量指定的指针表示形式。等同于/vmg选项
best_case 为所有成员指针使用最佳情况(best__case)表示生成安全的最优代码。使用该参量是需在定义一个类的成员指针说明之前定义此类。其缺省值为best_case
best_case 为所有成员指针使用最佳情况(best__case)表示生成安全的最优代码。使用该参量是需在定义一个类的成员指针说明之前定义此类。其缺省值为best_case
最一般表示参量说明了在转换单元中,编译器能够安全地引用任何指向类成员的指针的最小指针表示。该参量取如下值之一:
参量 说明
single_inheritance 最一般表示是单继承的,即一个成员函数的指针。对于其中说明了一个指向成员指针的一个类定义,若其继承模式说明为多重的或虚拟的,将导致错误
multiple_inheritance 最一般表示是多重继承的,即一个成员函数的指针。对于其中说明了一个指向成员指针的一个类定义,若其继承模式是虚拟的,将导致错误
vitual_inheritance 最一般表示是虚拟继承,即一个成员函数的指针。该函数不会导致错误。当使用#pragma pointers_to_members(full_generality) 时这是个缺省参量
vtordisp
#pragma vtordisp({on|off})
该指令允许增加隐含的vtordisp构造函数/析构函数替换成员。vtordisp编译指示只使用虚基类的代码。
若一个派生类重迭一个从虚拟基类继承的虚拟函数,且如果派生类的一个构造函数或析构函数调用那个使用该虚拟基类指针的函数,则编译器可能将增加的隐含“vtordisp”域到有虚拟基的类中。
vtordisp 编译指示会影响其后类的分布。/Vd0或/Vd1选项指定了对于完全模式的相同动作。
指定off将抑制隐含的vtordisp成员。指定缺省值on,将在需要的位置打开它们。
Vtordisp指令仅在类的构造/析构函数在用this指针指向的对象处不可能调用虚拟函数时关闭。
#pragma vtordisp(off)
class GetReal:virtual public{...};
#pragma vtordisp(on)
以上为C++特殊的
-------------------------------------------------------------
alloc_text
#pragma alloc_text(“文本段”,函数1,...)
该指令用于命名指定的函数定义将要驻留的代码段。该编译指示对已命名的函数必须出现在一个函数说明符和该函数定义之间。
alloct_text编译指示并不处理C++成员函数或重载函数。它仅用于以C连接方式说明的函数,这指的是用extern“C”连接规格说明的函数。如果你试图将此编译指示用于非C++连接的函数,将产生一个编译错误。
由于不支持使用__based的函数地址,指定段位址需要使用alloc_text编译指示,以文本段指定的名称应包括在双引号间。
alloc_text 编译指示必须出现在指定的函数说明之后,这些函数的定义之前。
一个alloc_text编译指示中的函数引用必须在此编译指示的同一模块中定义。如果未这样做,且一个未定义的函数随后被编译到一个不同的文本段,则这个错误可能找得到,也可能找不到。虽然该程序一般会正常运行,但该函数不会分配到预期的段中。
alloc_text的其他限制如下:
* 它不能用在一个函数的内部。
* 它必须在已说明的函数之后和已定义的函数之前使用。
auto_inline
#pragma auto_inline([{on|off}])
排除自动内联扩展的候选者中指定为off的区域中定义的函数。
为了使用auto_inline编译指示,把它放在一个函数定义之前或立即之后(不在该函数定义之内)。
在看到该编译指示之后的第一个函数定义处,该编译指示发生作用。编译指示auto_inline不能应用于显式内联函数。
bss_seg
seg#pragma bss-seg(["section-name"[,"section-class"]])
指定未初始化数据的缺省段。data_seg编译指示处理初始化或未初始化数据有相同的作用。在某些情况下,你可以使用bss_seg通过把所有未初始化数据放在一个段中来加速加载的时间。
#pragma bss_seg("MY_DATA")
导致#pragma语句后未初始化的数据分配到一个名称为MY_DATA的段中。
用bss_seg编译指示分配的数据不会保留关于它的位置的任何信息。
第二个参量section_class用于与Visual C++之前的版本兼容,现在已被忽略。
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 - 是或否 关闭其后函数的栈检查
code_seg
#pragma code_seg(["section-name"[,"section-class"]])
该指令用于指定一个分配函数的代码段。code_seg编译指示指定了函数的缺省段。
你可以有选择性地指定类和段名。使用没有section-name字符串的#pragmacode_seg可在编译开始时将其复位。
const_seg
#pragma const_seg(["section-name"[,"section-class"]])
该指令用于指定对于常量数据的缺省段。data_seg编译指示对所有数据具有相同作用。你可以用此指令将你的所有常量数据放入一个只读段中。
#pragma const_seg("MY_DATA")
导致该指令将#pragma语句后的常量数据放入一个名称为MY_DATA的段里。
使用const_seg编译指示分配的数据不会保留有关它的位置的任何信息。
第二个参数section-class用于与 Visual C++ 2.0 版之前的版本兼容,现在已可忽略。
comment
#pragma comment(comment-type,[commentstring])
该指令将一个注释记录放入一个对象文件或可执行文件中。
comment-type是下面五种说明的预定义标识符之一,它们指出了注释记录的类型。任选的commentstring是给一些注释类型提供额外信息的字符串文字。
由于commentstring是一个字符串文字,因此它必须遵循对于字符串文字的诸如转义字符、嵌lib
该选项将一个库搜索记录放入对象文件。
该注释类型必须带有一个commentstring参数。这个参数包含你想要的链接器搜索的库的名称(有可能包含路径)。
由于在对象文件中该库名称在缺省的库搜索记录之前,所以链接器搜索该库就象你在命令行中命名了它一样。
你可以把多个库搜索记录放在同一个源文件中,每个记录在对象文件中都以其在源文件中出现的同样顺序出现。
linker
该选项将一个链接器选项放入对象文件中。可以用该注释类型指定一个链接器选项,用于取代在Project Setting对话框中Link选项卡上放入该选项。
例如,你可以指定/include选项来强行包括一个符号:
#pragma comment(linker,"/include:__symbol")
user
该选项将一个一般的注释放入对象文件中。commentstring参量包含了该注释的文本。这个注释记录被链接器忽略。
以下编译指示导致链接器在连接时搜索EMAPI.LIB库。该连接器首先在当前工作目录中搜索,随后在LIB环境变量说明的路径中搜索。
lib
#pragma comment(lib,"emapi")
以下编译指示导致编译器把编译器的名称和版本号放入对象文件:
complier
#pragma comment(complier)
注意:对于一个带commentstring参量的注释,你可以在任何要使用一个字符串文字的地方使用宏,让这个宏扩展为一个字符串文字。
你也可以把任何一个字符串文字的任何组合与扩展为字符串文字的宏合并起来,例如:下面的语句是可以接受的:
#pragma comment(user,"Compiled on" __DATA__ "at" __TIME__ )
browser
#pragma component(browser,{on|off}[,references[,name]])#pragma component(minrebuild,on|off)
该指令用于控制源文件内的浏览信息或依赖信息的集合。
你可以打开或关闭集合,并可以在收集信息时指定忽略的特定名称。
用on或off选项控制前面编译指示的浏览信息的集合。例如:
#pragma component(browser,off)
该指令让编译器停止收集浏览信息。
注意:用此指令打开浏览信息的集合,浏览信息必须先用Project Settings对话框或命令行打开。
references选项可带也可不带name参量。不带name参量的references选项用于打开或关闭引用的集合(但此时继续收集其它浏览信息)。例如:
#pragma component(browser,off,references)
该指令使编译器停止收集引用信息。
带name和off参量的references选项,用于防止浏览信息窗口中出现对name的引用。
使用这种语法可忽略你不感兴趣的名称和类型, 并且可缩短浏览信息的尺寸。例如:
#pragma component(browser,off,references,DWORD)
忽略该点之前对于DWORD的引用。但你可用on选项把对于DWORD引用的集合重新打开。
#pragma component(browser,on,references,DWORD)
这是恢复对name引用集合唯一的方式;用此方式你可以显式地打开任何你已经关闭的name。
为了防止预处理器把name展开(如把NULL扩展为0),将它加上引号:
#pragma component(browser,off,references,"NULL")
Minimal Rebuild
Visual C++的minimal rebuild(最小重建)特性需要编译器创建和存储依赖信息的C++类,这将占用磁盘空间。
为了节省磁盘空间,你可以在任何你不需收集依赖信息的时候仅用#pragma component(minirebuild,off),例如,在不变的头文件中。
在不变的类后插入#pragma component(minrebuild,on)可重新打开依赖信息。
有关更多的信息参见Enable Minimal Rebuild(/Gm)编译器选项。
data_seg
#pragma data_seg(["section-name"[,"section-class"]])
该指令指定数据的缺省段。例如:
#pragma data_seg("MY_DATA")
将#pragma语句后分配的数据放在以名称为MY_DATA的段里。
使用data_seg编译指示分配的数据不会保留关于它的位置的任何信息。
第二个参量section-class用于与Visual C++ 2.0 之前的版本兼容,现在已可忽略。
function
#pragma function(function1[,function2,...])
该指令指定对在生成的编译器编译指示参量表中指定调用的函数。如果你使用intrinsic编译指示(或/Oi)告诉编译器生成内在函数
(被生成为内联代码,而非函数调用的内在函数),就能用function编译指示来显式地强制调用一个函数。
当一个函数编译指示出现时,它在第一个包含一个指定的内在函数的函数定义处发生作用,
这个作用持续到源文件的结尾或直到一个说明这种相同的内在函数的编译指示出现为止。
在全局层时,该function编译指示只能用在一个函数外。对于具有内部形式的函数表,参见#pragma intrinsic。
hdrstop
#pragma hdrstop[("filename")]
该指令用于控制预编译头文件的工作方式。filename是预编译头文件使用或创建的名称(根据指定选项/Yu或/Yc决定)。
如果filename不包含路径说明,预编译头文件将被假定在与源文件相同的目录中。当指定/YX自动预编译头文件选项时,所有filename都被忽略。
当采用/YX或/Yc编译时,一个C或C++文件包含一个hdrstop编译指示,该编译器将把编译状态存入到编译指示的位置。
该编译指示之后任何代码的编译状态都不存储。
hdrstop编译指示不可能出现在一个头文件中。它必须出现在源文件中。这指的是,它不能出现在任何数据、函数说明或函数定义中。
注意:除非/YX选项或无文件名的/Yu或/Yc选项被指定,否则hdrstop编译指示将被忽略。
该指令使用filename命名编译状态存储的预编译头文件。hdrstop和filename之间的一个空白是任选的。
在hdrstop编译指示中说明的文件名称是一个字符串,而且必须服从C或C++字符串的约束。尤其重要的是必须将其置于括号中
如下例所示:
#pragma hdrstop("c:\projects\include\myinc.pch")
预编译头文件的名称由下列规则决定,顺序如下:
1. /Fp编译器选项的参量。
2. #pragma hdrstop的filename参量。
3. 以.PCH为扩展名的源文件的基名称。
include_alias
#pragma include_alias("long_filename","short_filename")
#pragma include_alias(,)
该指令指定short_filename作为long_filename的别名。某些文件系统允许比 8.3 FAT文件系统限定更长的文件名。
编译器不能够简单地把更长的头文件名截短为 8.3 格式,因为这种更长的头文件名的开始八个字符可能不是唯一的。
只要编译器遇到long_filename字符串,就用short_filename替换,并且代替查找short_filename头文件。
这个编译指示必须出现在相应的#include指令之前,
例如:/
/这两个文件的开头八个字符不是唯一的
#pragma include_alias("AppleSystemHeaderQuickdraw.h","quickdra.h")
#pragma include_alias("AppleSystemHeaderFruit.h","fruit.h")
#pragma include_alias( "GraphicsMenu.h", "gramenu.h")
#include "AppleSystemHeaderQuickdraw.h"
#include "AppleSystemHeaderFruit.h"
#include "GraphicsMenu.h"
无论是拼写,还是双引号或尖括号的用法,被搜索的别名都必须符合规格。include_alias编译指示在该文件名中处理简单的字符串匹配,而在其它的文件名中是无效的。
例如,给出如下指令:
#pragma include_alias("mymath.h","math.h")
#include "./mymath.h"
#include "sys/mymath.h"
没有别名使用(替换)被执行,因为头文件字符串并不匹配。用作/Yu、/Yc和/YX编译器选项参量的头文件名,或hdrstop编译指示的头文件名也不能被替换。
例如,若你的源文件包含下列指令:
#include
相应的编译器选项应该是:
/YcAppleSystemHeaderStop.h
你可以用include_alias编译指示把任何头文件名映射为另一个。例如:
#pragma include_alias("api.h", "c:\version1.0\api.h")
#pragma include_alias(, )
#include "api.h"
#include
不要把双引号内的文件名和尖括号内的文件名相混淆,例如,对于上面给出的两个#pragma include_alias指令,编译器在下面的#include指令中不执行任何替换:
#include
Include "stdio.h"
此外,下面的指令将导致错误:
#pragma include_alias(,"header.h") //错误
注意在错误信息中给出的文件名,或作为预先定义的__FILE__宏的值,是替换执行之后的文件的名称,例如,下面指令后:
#pragma include_alias("VeryLongFileName.H","myfile.h")
#include "VeryLongFileName.H"
在VERYLONGFILENAME.H中的一个错误将导致如下错误消息:
myfile.h(15) : error c2059 : syntax error
同时注意传递性是不支持的。如下指令中:
#pragma include_alias( "one.h", "two.h" )
#pragma include_alias( "two.h", "three.h")
#include "one.h"编译器搜索的是文件TWO.H而不是THREE.H。
inline_depth
#pragma inline_depth([0...255])
该指令通过控制一系列函数调用能被扩展的次数(从0到255次),来控制内联扩展可发生的次数。
这个编译指示控制标记为inline和__inline的函数的联编或在/Ob2选项下已经自动联编的函数。
inline_depth编译指示控制一序列函数调用能被扩展的次数,例如,若联编深度为4,且若A调用B,B调用C,三个调用都将内联扩展。
但如果最近的内联扩展为2,只有A和B被扩展,C保留为一个函数调用。
为使用这个编译指示,你必须设置/Ob编译器选项为1或2。
使用这个编译指示的深度设置在该编译指示指令后的第一个函数处生效。如果你没有在圆括号中指定一个值,inline_depth将设置联编深度为缺省值8。
联编深度在扩展时只减不增。若联编深度为6,且在扩展时,预处理器遇到一个联编深度值为8的inline_depth编译指示,该深度仍保持为6。
联编深度0禁止联编扩展;联编深度255对联编扩展无限制,若使用一个未指定其值的编译指示,则将使用其缺省值。
inline_recursion
#pragma inline_recursion([{on|off}])
该指令控制直接或相互递归函数调用的联编扩展。该指令用于控制标记为inline和__inline的函数,或编译器在Ob2选项下自动扩展的函数。
这个编译指示的用法需要一个设置为1或2的/Ob编译器选项。inline_recursion的缺省状态是off。
这个编译指示只是在其出现之后的第一个函数处起作用,并且不会影响该函数的定义。
inline_recursion 编译指示控制递归函数如何被扩展。
如果inline_recursion关闭,且若一个联编函数调用其自身(直接或间接),该函数只被扩展一次。
若inline_recursion为打开状态,则该函数将被扩展多以下所列的浮点函数没有真正的内在格式。
但它们有这样的版本:将参量直接送入浮点芯片, 而不是将它们压入程序栈中:
acos cosh pow tanh asin fmod sinh
当你指定/Oi和/Og编译器选项(或任何包括/Og、/Ox、/O1和/O2的选项)时,以下浮点函数有真正的内在格式:
atan exp log10 sqrt atan2 log sin tan cos
你可以使用/Op或/Za编译器选项重迭真正的内在浮点选项的生成。
这种情况下,该函数被生成为库例程,该例程直接把参量送入浮点芯片,而不是把它们压入程序栈。
message
#pragma message(messagestring)
该指令不终止编译,直接把一个字符串文字送到标准输出。message编译指示的典型用法是在编译时显示信息消号。
以下代码段使用message编译指示在编译时显示一个消息:
#if _M_IX86==500
#pragma
message("Pentium processor build")
#endif
messagestring参数可以是可扩展为一个字符串文字的宏,并且你可以以任何组合方式用字符串文字将这些宏合并起来。
例如,下列语句显示了被编译的文件名以及该文件最后改动的日期和时间:
#pragma message("Compiling "__FILE__ )
#pragma message("Last modified on " __TIMESTAMP__)
once
#pragma once
该指令指定该编译指示驻留的文件将只在一次建立中被编译器包括(打开)一次。该编译指示的一种普通用法如下:
//header.h
#pragma once
//接着是你的C或C++代码
optimize
#pragma optimize( "[optimization-list]",{on|off} )
仅用于专业和企业版本的特征:代码优化只被Visual C++专业版和企业版支持。更多的信息参见Microsoft Visual C++联机编辑。
该指令指定在函数基中执行的优化。
optimize编译指示必须出现在一个函数之外,并且在编译指示出现后定义的第一个函数处产生作用。
on和off参量可以打开或关闭在Optimization-list中指定的选项。
optimization-list可以是0或在表2.2中给出参数。
表 2.2 "优化"编译指示的参数
参量 优化类型
a 假定无别名
g 允许全局优化
p 提高浮点相容性
s或t 指定机器码的短或快序列
w 假定无交叉函数调用的别名
y 生成程序堆栈中的框架指针
这些是采用/O编译器选项的相同字母,例如:
#pragma optimize("atp", on)
用空字符串("")使用optimize编译指示是该指令的一种特殊形式,它可关闭所有的优化或恢复它们的原有(缺省的)设置。
#pragma optimize("",off)
...
#pragma optimize("", on)
pack
#pragma pack([n])
该指令指定结构和联合成员的紧凑对齐。而一个完整的转换单元的结构和联合
的紧凑对齐由/Zp选项设置。
紧凑对齐用pace编译指示在数据说明层设置。该编译指示在其出现后的第一个结构或联合说明处生效。
该编译指示对定义无效。
当你使用#pragma pack(n)时,这里n为1、2、4、8或16。第一个结构成员之后的每个结构成员都被存储在更小的成员类型或n字节界限内。
如果你使用无参量的#pragma pack,结构成员被紧凑为以/Zp指定的值。该缺省/Zp紧凑值为/Zp8。
编译器也支持以下增强型语法:
#pragma pack([[{push|pop},][标识符,]][n])
若不同的组件使用pack编译指示指定不同的紧凑对齐,这个语法允许你把程序组件组合为一个单独的转换单元。
带push参量的pack编译指示的每次出现将当前的紧凑对齐存储到一个内部编译器堆栈中。
编译指示的参量表从左到右读取。如果你使用push,则当前紧凑值被存储起来;如果你给出一个n的值,该值将成为新的紧凑值。
若你指定一个标识符,即你选定一个名称,则该标识符将和这个新的的紧凑值联系起来。
带一个pop参量的pack编译指示的每次出现都会检索内部编译器堆栈顶的值,并且使该值为新的紧凑对齐值。
如果你使用pop参量且内部编译器堆栈是空的,则紧凑值为命令行给定的值,并且将产生一个警告信息。若你使用pop且指定一个n的值,该值将成为新的紧凑值。
若你使用pop且指定一个标识符,所有存储在堆栈中的值将从栈中删除,直到找到一个匹配的标识符,
这个与标识符相关的紧凑值也从栈中移出,并且这个仅在标识符入栈之前存在的紧凑值成为新的紧凑值。
如果未找到匹配的标识符,将使用命令行设置的紧凑值,并且将产生一个一级警告。缺省紧凑对齐为8。
pack编译指示的新的增强功能让你编写头文件,确保在遇到该头文件的前后的紧凑值是一样的。
/* File name: include1.h*/
#pragma pack(push,enter_include1)
/* 你的包括文件代码... */
#pragma pack(pop, enter_include1)
/* include1.h结束 */
在上面的例子中,当前紧凑值与标识符enter_include1联系起来,并被压入头文件的项中。
头文件末尾的pack编译指示删除所有可能出现在头文件中的干预紧凑值,并且删除与enter_include1相关的紧凑值。因此确保该头文件的前后的紧凑值是相同的。
这种新功能也允许你使用代码,例如头文件,它可以使用pack编译指示设置不同于在你的代码中设置的紧凑值的紧凑对齐:
#pragma pack(push,before_include1)
#include "include1.h"
#pragma pack( pop,before_include1)
在上面的例子中,对于出现在include.h中的紧凑值的任何变化,你的代码是受到保护的。
setlocale
#pragma setlocale("locale_string")
该指令在翻译宽字符常量和字符串文字时定义其场所(国家和语言)。
由于用于转换多字节字符为宽位字符的算法可能由于场所或编译而不同,该执行文件在不同的场所运行也可能不同。
这个编译指示提供了在编译时给出目标场所的方法。这保证了宽字符串以正确的格式进行存储。缺省的locale_string(场所字符串)是 “C”。
“C”场所将每个该串中的字符映射为一个wchar_t(unsigned short)型的值。
warning
#pragma warning( warning-specifier:warning-number-list [,warning-specifier:warning-number-list...])
#pragma warning(push[,n])#pragma warning(pop)
该指令允许选择性地改变编译器的警告消息。
warning-specifier可以是如下值之一:
警告指示符 含义
once 只显示一次指定的消息default将缺省的编译器行为应用于指定的消息
1,2,3,4 把给定的警告级应用于指定的警告消息
disable 不发出指定警告消息
error 作为错误报告指定的警告
warning-number-list(警告编号表)可以包含任何警告编号。在相同的编译指示指令中可指定多个选项如下:
#pragma warning( disable : 4507 34; once : 4385; error : 164 )其功能想当于:
#pragma warning( disable : 4507 34 )
// 禁止警告消息4507和34.#pragma warning( once : 4385 )// 仅发出警告4385一次
#pragma warning( error : 164 )// 作为一个错误报告警告164
对于那些与代码生成有关,且大于4699的警告编号来说,这个warning编译指示仅当放在函数定义外时有效。
如果警告编号大于4699或用在函数体内,则忽略该编译指示。下面的例子指出了禁止warning编译指示的正确位置,且随后恢复一个代码生成警告消息的产生。
int a;
#pragma warning( disable : 4705 )
void func()
{
a;
}
#pragma warning( default : 4705 )
warning编译指示也支持以下语法:
#pragma warning( push[,n])
#pragma warning( pop)
这里n代表警告级(1到4)。
编译指示warning(push)存储所有警告的当前警告状态。编译指示warning(push,n)存储所有警告的当前警告状态并设置全局警告级为n。
编译指示warning(pop)将上次压入栈的警告状态弹出,push和pop之间警告状态的任何变化都将被取消。考虑这个例子:
#pragma warning(push)
#pragma warning(disable : 4705)
#pragma warning(disable : 4706)
#pragma warning(disable : 4707)
// 某些代码
#pragma warning(pop)
在这段代码的未尾,pop恢复所有警告状态(包括4705、4706和4707)为它在代码起始处的警告状态。
当你编写头文件时,可以用push和pop以确保对于用户造成的警告状态的变化,不会影响头部的正确编译。
通常在头部的起始处使用push,在末尾处使用pop。
例如, 有一个在警告级4未彻底编译的头部。以下代码将警告级改为3,然后在头部的未尾恢复原来的警告级:
#pragma warning(push,3)
//说明/定义
#pragma warning(pop)
BCB6中的#Pragma说明
1.#pragma alignment
alignment pragma用于显示一条当前内存对齐(alignment)和枚举(enum)字节大小的消息。
例如:
W8035: The alignment is 8 bytes, the enum size is 4 bytes
该消息必须在打开编译器选项“show general messages”或编译器开关“-wmsg”后才能显示。
2.#pragma anon_struct
#pragma anon_struct on 允许编译类中内嵌的匿名结构
#pragma anon_struct off 禁止编译类中内嵌的匿名结构
例如:
#pragma anon_struct on
struct S
{
int i;
struct // Embedded anonymous struct
{
int j ;
float x ;
};
S() { i = 1; }
};
#pragma anon_struct off
3.#pragma argsused
argsused pragma通常在定义一个函数前使用,用于屏蔽函数参数未使用的警告。例如:
#pragma argsused
int func(int a,int b)
{
++b;
return b;
}
如果不使用该pragma,编译器就会报类似“函数参数没有用到”的警告消息。
4.#pragma checkoption optionstring
checkoption pragma检查optionstring中包含的选项是否已设置。例如:
#pragma checkoption -a4 –b
如果没有设置,显示一个错误:E2471: pragma checkoption failed: options are not as expected。
5.#pragma codeseg
#pragma codeseg <seg_name> <"seg_class"> <group>
codeseg pragma用于重命名函数代码所在的段(segment)、类(class)、组(group)。如果codeseg后没有任何选项,表示使用缺省代码段。
6.#pragma comment
#pragma comment (comment type, "string")
comment pragma用于将一个comment记录写入到输出文件。Comment类型可以下列值之一:
exestr 编译器将string写入到一个.obj文件中,最终放置到可执行文件中。使用文件搜索工具可以从可执行文件中找到该string。
lib 连接器将一个string中指定的.lib文件写入到一个.obj文件中。
user 编译器将string写入到一个.obj文件中,但连接器忽略,就是说最终string不放置到可执行文件中。
7.#pragma defineonoption and #pragma undefineonoption
#pragma defineonoption name switch(es)
#pragma undefineonoption name switch(es)
这两个pragma用于为若干个命令行开关建立一个别名(name)。除了部分负责输入的命令行开关(如-I、-L)外,大部分命令开关都可以在这两个指示符中使用。
#pragma defineonoption在别名中所有指定开关都已打开的情况下定义name。
#pragma undefineonoption在别名中所有指定开关都已打开的情况下不定义name。
例如,myfile.c文件包含下列代码:
#pragma defineonoption OPTIMIZING -O2
#ifdef OPTIMIZING
#pragma message We are optimizing with -O2
#else
#pragma message There are no optimizations turned on
#endif
bcc32 -c myfile.c,输出是There are no optimizations turned on
bcc32 -c -O2 myfile.c,输出是We are optimizing with -O2
下面是一个同时使用多个命令行开关的实例:
#define SWITCHES_ARE_OFF
#pragma undefineonoption SWITCHES_ARE_OFF -O2 -c -P -C
#ifdef SWITCHES_ARE_OFF
#pragma message At least one of the switches is not turned on
#else
#pragma message All switches are turned on
#endif
bcc32 -c myfile.c,输出是At least one of the switches is not turned on
bcc32 -c -P -O2 -C,输出是All switches are turned on
8. #pragma exit and #pragma startup
#pragma startup function-name <priority>
#pragma exit function-name <priority>
含义如下:
第一个pragma表示在main函数被called之前先call名为function-name这个函数。
第二个pragma表示在程序通过_exit退出之前,call名为function-name这个函数。
但是function-name这个函数,必须是不携带参数,且不返回值的函数,即:
void func(void);
priority参数数值范围为64-255,0值级别最高。级别越高,在main函数调用前越早调用,在-exit函数调用前越晚调用。缺省级别为100。0-63级别C库保留使用。
9.#pragma hdrfile
#pragma hdrfile "filename.CSM"
hdrfile pragma用于指定预编译头文件的名称。前提是必须已启用预编译头文件功能。
10.#pragma hdrstop
#pragma hdrstop
hdrstop pragma用于终止若干个头文件的预编译,可有效减少预编译头文件占用的磁盘空间。
凡在源文件中#pragma hdrstop指令之前被引用的头文件都将被预编译成预编译头文件。
假如一个头文件同时被多个源文件引用,那么生成的预编译头文件同样可被多个源文件共享。
因此,在工程中#pragma hdrstop指令之前包含通用头文件可获得更好的编译性能。
例如,一个新应用程序创建后,源文件“Unit1.cpp”都会包含类似内容:
#include <vcl.h> // common header file
#pragma hdrstop // terminate list here
#include "Unit1.h" // specific header file
#pragma hdrstop指令只能在源文件中使用,头文件中使用没有任何效果。
11.#pragma inline
#pragma inline
该指令等同于“-B”命令行选项。.
#pragma inline指令最好放在源文件的顶部,因为编译器每次遇到#pragma inline指令都会加上“-B”命令行选项重新编译该文件。
12.#pragma intrinsic
#pragma intrinsic [-]function-name
#pragma intrinsic用于重写控制函数内联的命令行开关或IDE选项。
内联一个指定的函数前必须包含该函数的原型。
例如:
#pragma intrinsic strcpy
编译器将在调用strcpy函数的函数内产生strcpy函数实现代码。
#pragma intrinsic –strcpy
阻止编译器对strcpy内联。
13.#pragma link
#pragma link “[path]modulename[.ext]”
该指令命令连接器将一个文件连接到可执行文件中。
缺省情况下,连接器缺省在本地路径下查找modulename文件,modulename文件后缀为“.obj”。
使用命令行选项“-L”或者path参数指定任意路径。
14.#pragma message
#pragma message ("text" ["text"["text" ...]])
#pragma message text
#pragma message (text)
使用这三个指令用于在程序代码中显示自定义的消息。
第一个指令用于输出一个消息,其中的宏不被展开。
第二个指令用于输出一个包含宏的消息,其中的宏将被展开。
第三个指令用于展开并输出一个已定义的宏。如果宏未被定义,将输出一个该指令无效的消息。
例如:
#ifdef __BORLANDC__
#pragma message you are compiling using version __BORLANDC__ of C++Builder.
#else
#pragma message “sorry,you are not using C++Builder compiler.”
#endif
14.#pragma obsolete
#pragma obsolete identifier
凡是在程序代码中该指令后遇到identifier标识符,预编译器将第一时间给出一个警告信息。警告显示该标识符已作废。
15.#pragma option
#pragma option options
#pragma option push options
#pragma option pop
#pragma nopushoptwarn
使用#pragma option指令用于在程序代码中包含命令行选项。#pragma option指令也可以附加push 和 pop参数后使用。
大部分命令行选项都可以作为options参数使用。options参数允许同时包含多个命令行选项。例如:
#pragma option -C
#pragma option -C –A
使用#pragma option push指令可以保存当前所有的命令行选项。
#pragma option pop指令和#pragma option push指令配对使用,用于恢复以前保存的命令行选项。
例如:
#pragma option push
#include <theworld.h>
#pragma option pop
#include “ystuff.h”
下面的实例因push和pop指令未配对使用,将会产生一个空栈警告。
#pragma option push
#pragma option pop
#pragma option pop /* Warning */
通过#pragma warn –nop指令可以关闭这个警告。
有一点必须特别注意,必须保证每个文件中的#pragma option push和#pragma option pop指令配对使用。
如果在文件结尾和文件开始时的命令行选项堆栈内容不一致,将会显示一个警告:“以前的选项和警告没有恢复?”。
通过#pragma nopushoptwarn.指令关闭这个警告。
16.#pragma pack
#pragma pack([{push | pop}[,]] [identifier[,]] [n])
#pragma pack(n)指令和#pragma option –an指令的作用是一样的。n表示编译器在内存中排列数据的字节对齐方式。
#pragma pack()表示选择编译器缺省的字节对齐方式,缺省为8字节。
#pragma pack(n)表示选择n值作为字节对齐方式。n可以为1,2,4,8和16。
#pragma pack(push) 表示压入当前字节对齐方式。
#pragma pack(push, ident) 表示关联标识符ident后压入当前字节对齐方式。
#pragma pack(push, n) 表示压入当前字节对齐方式,选择n值作为字节对齐方式。
#pragma pack(push, ident, n) 表示关联标识符ident后压入当前字节对齐方式,选择n值作为字节对齐方式。
#pragma pack(pop) 表示弹出最后压入的字节对齐方式。
#pragma pack(pop, ident) 表示弹出关联标识符ident的字节对齐方式。如果没有找到该标识符,选择缺省字节对齐方式。
#pragma pack(pop,n) 表示弹出n值大小的字节对齐方式。如果没有找到匹配的内容,选择缺省字节对齐方式。
#pragma pack(pop, ident,n) 表示弹出关联标识符ident的n值大小的字节对齐方式。如果没有找到匹配的内容,选择缺省字节对齐方式。
#pragma pop指令必须和#pragma push指令配对使用。
#pragma 详解
最新推荐文章于 2017-02-19 09:14:01 发布