当前位置:文档之家› C++ #pragma预处理命令

C++ #pragma预处理命令

#pragma预处理命令#pragma可以说是C++中最复杂的预处理指令了,下面是最常用的几个#pragma 指令:#pragma comment(lib,"XXX.lib")表示链接XXX.lib这个库,和在工程设置里写上XXX.lib的效果一样。

#pragma comment(linker,"/ENTRY:main_function")表示指定链接器选项/ENTRY:main_function#pragma once表示这个文件只被包含一次#pragma warning(disable:4705)表示屏蔽警告4705C和C++程序的每次执行都支持其所在的主机或操作系统所具有的一些独特的特点。

例如,有些程序需要精确控制数据存放的内存区域或控制某个函数接收的参数。

#pragma为编译器提供了一种在不同机器和操作系统上编译以保持C和C++完全兼容的方法。

#pragma是由机器和相关的操作系统定义的,通常对每个编译器来说是不同的。

如果编译器遇到不认识的pragma指令,将给出警告信息,然后继续编译。

Microsoft C and C++ 的编译器可识别以下指令:alloc_text,auto_inline,bss_seg,check_stack,code_seg,comment,component,conform,const_seg,data_seg,deprecated,fenv_access,float_control,fp_contract,function,hdrstop,include_alias,init_seg,inline_depth,inline_recursion,intrinsic,make_public,managed,message,omp,once,optimize,pack,pointers_to_members,pop_macro,push_macro,region, endregion,runtime_checks,section,setlocale,strict_gs_check,unmanaged,vtordisp,warning。

其中conform,init_seg, pointers_to_members,vtordisp仅被C++编译器支持。

以下是常用的pragma指令的详细解释。

1.#pragma once。

保证所在文件只会被包含一次,它是基于磁盘文件的,而#ifndef 则是基于宏的。

2.#pragma warning。

允许有选择性的修改编译器的警告消息的行为。

有如下用法:#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号警告信息作为一个错误#pragma warning(default:176) // 重置编译器的176号警告行为到默认状态同时这个pragma warning也支持如下格式,其中n代表一个警告等级(1---4):#pragma warning(push) // 保存所有警告信息的现有的警告状态#pragma warning(push,n) // 保存所有警告信息的现有的警告状态,并设置全局报警级别为n#pragma warning(pop) //例如:#pragma warning(push)#pragma warning(disable:4705)#pragma warning(disable:4706)#pragma warning(disable:4707)#pragma warning(pop)在这段代码后,恢复所有的警告信息(包括4705,4706和4707)。

3.#pragma hdrstop。

表示预编译头文件到此为止,后面的头文件不进行预编译。

BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。

4.#pragma message。

在标准输出设备中输出指定文本信息而不结束程序运行。

用法如下:#pragma message("消息文本")。

当编译器遇到这条指令时就在编译输出窗口中将“消息文本”打印出来。

5.#pragma data_seg。

一般用于DLL中,它能够设置程序中的初始化变量在obj 文件中所在的数据段。

如果未指定参数,初始化变量将放置在默认数据段.data 中,有如下用法:#pragma data_seg("Shared") // 定义了数据段"Shared",其中有两个变量a和bint a = 0; // 存储在数据段"Shared"中int b; // 存储在数据段".bss"中,因为没有初始化#pragma data_seg() // 表示数据段"Shared"结束,该行代码为可选的对变量进行专门的初始化是很重要的,否则编译器将把它们放在普通的未初始化数据段中而不是放在shared中。

如上述的变量b其实是放在了未初始化数段.bss 中。

#pragma data_seg("Shared")int j = 0; // 存储在数据段"Shared"中#pragma data_seg(push, stack1, "Shared2") //定义数据段Shared2,并将该记录赋予别名stack1,然后放入内部编译器栈中int l = 0; // 存储在数据段"Shared2"中#pragma data_seg(pop, stack1) // 从内部编译器栈中弹出记录,直到弹出stack1,如果没有stack1,则不做任何操作int m = 0; // 存储在数据段"Shared"中,如果没有上述pop段,则该变量将储在数据段"Shared2"中6.#pragma code_seg。

它能够设置程序中的函数在obj文件中所在的代码段。

如果未指定参数,函数将放置在默认代码段.text中,有如下用法:void func1() { // 默认存储在代码段.text中 }#pragma code_seg(".my_data1")void func2() { // 存储在代码段.my_data1中 }#pragma code_seg(push, r1, ".my_data2")void func3() { // 存储在代码段.my_data2中 }#pragma code_seg(pop, r1)void func4() { // 存储在代码段.my_data1中 }7.#pragma pack。

用来改变编译器的字节对齐方式。

常规用法为:#pragma pack(n) //将编译器的字节对齐方式设为n,n的取值一般为1、2、4、8、16,一般默认为8#pragma pack(show) //以警告信息的方式将当前的字节对齐方式输出#pragma pack(push) //将当前的字节对齐方式放入到内部编译器栈中#pragma pack(push,4) //将字节对齐方式4放入到内部编译器栈中,并将当前的内存对齐方式设置为4#pragma pack(pop) //将内部编译器栈顶的记录弹出,并将其作为当前的内存对齐方式#pragma pack(pop,4) //将内部编译器栈顶的记录弹出,并将4作为当前的内存对齐方式#pragma pack(pop,r1) //r1为自定义的标识符,将内部编译器中的记录弹出,直到弹出r1,并将r1的值作为当前的内存对齐方式;如果r1不存在,当不做任何操作一个例子:以如下结构为例: struct {char a;WORD b;DWORD c;char d;}在Windows默认结构大小: sizeof(struct) = 4+4+4+4=16;与#pragma pack(4)一样若设为#pragma pack(1), 则结构大小: sizeof(struct) = 1+2+4+1=8;若设为#pragma pack(2), 则结构大小: sizeof(struct) = 2+2+4+2=10;在#pragma pack(1)时:空间是节省了,但访问速度降低了;有什么用处???在系统通讯中,如和硬件设备通信,和其他的操作系统进行通信时等,必须保证双方的一致性。

8.#pragma comment。

将一个注释记录放置到对象文件或可执行文件中。

其格式为:#pragma comment( comment-type [,"commentstring"] )。

其中comment-type是一个预定义的标识符,指定注释的类型,应该是compiler,exestr,lib,linker,user之一。

compiler:放置编译器的版本或者名字到一个对象文件,该选项是被linker忽略的。

exestr:在以后的版本将被取消。

lib:放置一个库搜索记录到对象文件中,这个类型应该与commentstring(指定Linker要搜索的lib的名称和路径)所指定的库类型一致。

在对象文件中,库的名字跟在默认搜索记录后面;linker搜索这个这个库就像你在命令行输入这个命令一样。

你可以在一个源文件中设置多个库搜索记录,它们在obj文件中出现的顺序与在源文件中出现的顺序一样。

如果默认库和附加库的次序是需要区别的,使用/Zl编译开关可防止默认库放到object模块中。

linker:指定一个连接选项,这样就不用在命令行输入或者在开发环境中设置了。

只有下面的linker选项能被传给Linker:1./DEFAULTLIB2./EXPORT3./INCLUDE4./MANIFESTDEPENDENCY5./MERGE6./SECTION(1)/DEFAULTLIB:library/DEFAULTLIB选项将一个library添加到LINK在解析引用时搜索的库列表。

用/DEFAULTLIB指定的库在命令行上指定的库之后和obj文件中指定的默认库之前被搜索。

忽略所有默认库(/NODEFAULTLIB)选项重写/DEFAULTLIB:library。

相关主题