#pragma
一、什么是#pragma
在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。简单来说:实现对其宿主机或操作系统唯一的功能;
二、指令详解
1.格式
2.#pragma once
只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。#ifndef,#define,#endif这个是C++语言相关,这是C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式
#ifndef ABCD_H #define ABCD_H // ... some declaration codes #endif // #ifndef ABCD_H效果等同于:#pragma once。
3.#pragma message
#pragma message("消息文本")当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法
#ifdef _X86 #pragma message("_X86 macro activated!") #endif当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated! ”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。
4.#pragma code_seg
5.#pragma hdrstop
#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。
有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。
6.#pragma resource
7.#pragma warning
#pragma warning(disable:450734;once:4385;error:164) //等价于: #pragma warning(disable:450734)//不显示4507和34号警告信息 #pragma warning(once:4385)//4385号警告信息仅报告一次 #pragma warning(error:164)//把164号警告信息作为一个错误。 //同时这个pragma warning 也支持如下格式: #pragma warning(push[,n]) #pragma warning(pop) //这里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)。
7.#pragma pack
这个在内存对齐已经详细记录过了,这里就来了解一下网络协议编程中的应用实例。在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。
#pragma pack(1)//按照1字节方式进行对齐 struct TCPHEADER { shortSrcPort;//16位源端口号 shortDstPort;//16位目的端口号 intSerialNo;//32位序列号 intAckNo;//32位确认号 unsignedcharHaderLen:4;//4位首部长度 unsignedcharReserved1:4;//保留16位中的4位 unsignedcharReserved2:2;//保留16位中的2位 unsignedcharURG:1; unsignedcharACK:1; unsignedcharPSH:1; unsignedcharRST:1; unsignedcharSYN:1; unsignedcharFIN:1; shortWindowSize;//16位窗口大小 shortTcpChkSum;//16位TCP检验和 shortUrgentPointer;//16位紧急指针 }; #pragm apop()//取消1字节对齐方式#pragma pack规定的对齐长度,实际使用的规则是: 结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 但是,当#pragma pack的值等于或超过最长数据成员的长度的时候,这个值的大小将不产生任何效果。 而结构整体的对齐,则按照结构体中最大的数据成员进行。