#pragma 预处理

 

#pragma 预处理指令它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作

对每个编译器给出了一个方法,在保持与 C 和 C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。

依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

其格式一般为:#pragma para   //其中 para 为参数

 

1、#pragma message

message 参数: 它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:

#pragma message(“消息文本”)     //当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。配合#if / #ifdef / #ifndef设置编译时的提示信息 

当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。

假设我们希望判断自己有没有在源代码的什么地方定义了_X86 这个宏:

#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif

当我们定义了_X86 这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated!”。

2、#pragma code_seg

另一个使用得比较多的 pragma 参数是 code_seg。格式如:#pragma code_seg( ["section-name"[,"section-class"] ] )

void func1() {                  // 默认存储在代码段.text中
}

#pragma code_seg(".my_data1")
void func2() {                  // 存储在代码段.my_data1中
}

#pragma  code_seg(“PAGE”)//作用是将此部分代码放入分页内存中运行。
#pragma  code_seg()     //将代码段设置为默认的代码段
#pragma  code_seg("INIT")//加载到INIT内存区域中,成功加载后,可以退出内存 

它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

 /*************************************************/
 2 /*               串口中端接受函数                */
 3 /*************************************************/
 4 #pragma CODE_SEG __NEAR_SEG NON_BANKED     //将接下来的代码(一般是中断函数)置于非分页区
 5 interrupt void recievedata(void) {
 6   data_recieve = SCI_recieve();
 7   if(data_recieve == 'O') {
 8     SCI_send('Y');
 9     LEDCPU = LED_ON;
10   }
11   if(data_recieve == 'C') {
12     LEDCPU = LED_OFF;
13   }
14 }
15 #pragma CODE_SEG DEFAULT   //后续代码置于默认区域内

3、#pragma once 

只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。

为了避免同一个头文件被包含(include)多次,C/C++中有两种宏实现方式:一种是 #ifndef方式;另一种是 #pragma once方式。

方式一:(常用)
    #ifndef _SOMEFILE_H_
    #define _SOMEFILE_H_
    ... ... // 一些声明语句
    #endif
方式二:
    #pragma once
    ... ... // 一些声明语句

#ifndef 的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况。

#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

方式一由语言支持所以移植性好,方式二可以避免名字冲突

4、#pragma hdrstop

#pragma hdrstop 表示预编译头文件到此为止,后面的头文件不进行预编译。通过使用该指示来减少预编译头文件所占用的磁盘空间。     

 

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

有时单元之间有依赖关系,比如单元 A 依赖单元 B,所以单元 B 要先于单元 A 编译。

可以用#pragma startup 指定编译优先级,如果使用了#pragma package(smart_init) , BCB就会根据优先级的大小先后编译。

5、#pragma resource

#pragma resource "*.dfm"表示把*.dfm 文件中的资源加入工程。*.dfm 中包括窗体外观的定义。

6、#pragma warning

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

once :只显示一次 (警告 /错误等 )消息 
default :重置编译器的警告行为到默认状态 
1 , 2 , 3 , 4 :四个警告级别 
disable:禁止指定的警告信息 
error :将指定的警告信息作为错误报告

#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 也支持如下格式:

i、#pragma warning( push [ ,n ] )   //这里 n 代表一个警告等级(1---4)。

#pragma warning( push )    //保存所有警告信息的现有的警告状态。

#pragma warning( push, n) //保存所有警告信息的现有的警告状态,并且把全局警告等级设定为 n。

ii、#pragma warning( pop )    //向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。

#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
//......
#pragma warning( pop )

在这段代码的最后,重新保存所有的警告信息 (包括 4705, 4706和 4707 )。

7、#pragma comment

该指令将一个注释记录放入一个对象文件或可执行文件中

i、常用的 lib 关键字,可以帮我们连入一个库文件。

#pragma comment(lib, "user32.lib")  //该指令用来将 user32.lib 库文件加入到本工程中。

ii、linker:将一个链接选项放入目标文件中,可以使用这个指令来代替由命令行传入的或者在开发环境中设置的链接选项,

可以指定/include 选项来强制包含某个对象,例如:

#pragma comment(linker, "/include:__mySymbol")

8、#pragma pack 的用法:

#pragma pack(n)       //n=1,2,4,8,16 保存当前对齐方式,设置按 字节对齐
#pragma pack ()             //取消自定义字节对齐方式
 
 
posted @ 2021-11-16 17:06  listxue  阅读(105)  评论(0编辑  收藏  举报