#pragma 预编译指令的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。

  其使用的格式一般为: #pragma Para。其中Para 为参数,常见的参数如下:

(1)Message参数

  Message参数编译信息输出窗口中输出相应地信息,使用方法如下:

#pragma message("消息文本")

  使用示例,假如在程序中我们定义了很多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法:

#ifdef _X86
#pragma message("_X86 macro activated!")
#endif

(2)code_seg参数

  code_seg参数可以设置程序中函数代码存放的代码段,使用方式如下:

#pragma code_seg(["section-name"[,"section-class"]])

(3)#program once 参数

  其作用是在在头文件的最开始加入这条指令,以保证头文件被编译一次。但#program once是编译器相关的,就是说在这个编译系统上能用,但在其他的编译系统上就不一定能用,所以其可移植性较差。一般如果强调程序跨平台,还是选择使用“#ifndef,   #define,   #endif”比较好。

(4)#program hdrstop

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

(5)#program resource

  #program resource  “*.dfm”表示把*.dfm文件中的资源添加到工程。

(6)#program comment

  #program comment将一个注释记录放入一个对象文件或可执行文件。

(7)#program data_seg

  #program data_seg用来建立一个新的数据段并定义共享数据。如下:

#pragma data_seg("shareddata")
HWNDsharedwnd=NULL;//共享数据
#pragma data_seg()

说明:a. #pragma data_seg()一般用于DLL中。也就是说,在DLL中定义一个共享的有名字的数据段。最关键的是:这个数据段中的全局变量可以被多个进程共享,否则多个进程之间无法共享DLL中的全局变量。

   b. 共享数据必须初始化,否则微软编译器会把没有初始化的数据放到.BSS段中,从而导致多个进程之间的共享行为失败。例如:

#pragma data_seg("MyData")
intg_Value;    //Note that the global is not initialized.
#pragma data_seg()
//DLL提供两个接口函数:
int GetValue()
{
return g_Value;
}
void SetValue(int n)
{
g_Value=n;
}

解释:启动两个进程A和B,A和B都调用了这个DLL,假如A调用了SetValue(5); B接着调用int m = GetValue(); 那么m的值不一定是5,而是一个未定义的值。因为DLL中的全局数据对于每一个调用它的进程而言,是私有的,不能共享的。假如你对g_Value进行了初始化,那么g_Value就一定会被放进MyData段中。换句话说,如果A调用了SetValue(5); B接着调用int m = GetValue(); 那么m的值就一定是5,这就实现了跨进程之间的数据通信。

(8)#program region

  #program region用于折叠特定的代码段,示例如下:

#pragma region Variables
HWND hWnd;
const size_t Max_Length = ;
//other variables
#pragma endregion This region contains global variables.

应用实例:在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。

协议的定义结构如下:

#pragma pack(1)  //按照1字节方式进行对齐
struct TCPHEADER
{
shortSrcPort;  //16位源端口号
shortDstPort;  //16位目的端口号
intSerialNo;  //32位序列号
intAckNo;    //32位确认号
unsignedcharHaderLen:;  //4位首部长度
unsignedcharReserved1:;  //保留16位中的4位
unsignedcharReserved2:;  //保留16位中的2位
unsignedcharURG:;
unsignedcharACK:;
unsignedcharPSH:;
unsignedcharRST:;
unsignedcharSYN:;
unsignedcharFIN:;
shortWindowSize;  //16位窗口大小
shortTcpChkSum;  //16位TCP检验和
shortUrgentPointer;  //16位紧急指针
};
#pragm apop()  //取消1字节对齐方式

#pragma pack规定的对齐长度,实际使用的规则是: 结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 但是,当#pragma pack的值等于或超过最长数据成员的长度的时候,这个值的大小将不产生任何效果。 而结构整体的对齐,则按照结构体中最大的数据成员进行。

本文学习内容参考:http://baike.baidu.com/link?url=Y2VbztMyL0ZfAA39g11DE3jPgGaaPhe9UXM4lKSsH6COB_90G8N2_W6bfA-tSBcE5ZYVGMYhqdghceMJ0_dyq_#1

http://blog.csdn.net/jx_kingwei/article/details/367312

C++ #pragma 预处理指令的更多相关文章

  1. #pragma 预处理指令详解

    源地址:http://blog.csdn.net/jx_kingwei/article/details/367312 #pragma  预处理指令详解              在所有的预处理指令中, ...

  2. pragma comment的使用 pragma预处理指令详解

    pragma comment的使用 pragma预处理指令详解   #pragma comment( comment-type [,"commentstring"] ) 该宏放置一 ...

  3. #pragma预处理指令讲解

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  4. C++中的#pragma 预处理指令详解

    源地址:http://blog.csdn.net/roger_77/article/details/660311 在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态 ...

  5. #pragma 预处理指令

    Linux C 编程一站式学习 #pragma 预处理指示供编译器实现一些非标准的特性,C 标准没有规定 #pragma 后面应该写什么以及起什么作用,由编译器自己规定.有的编译器用 #pragma ...

  6. C/C++预处理指令

    预处理指令 Preprocessor Directives define undef ifdef ifndef if endif else and elif line error include 预定 ...

  7. 预处理指令#pragma

    #pragma介绍 #pragma是一个预处理指令,pragma的中文意思是『编译指示』.它不是Objective-C中独有的东西(貌似在C/C++中使用比较多),最开始的设计初衷是为了保证代码在不同 ...

  8. 预处理指令中#Pragma

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  9. C/C++预处理指令#define,#ifdef,#ifndef,#endif…

    2016年12月29日更新: 今天查看以前文件的时候, 突然发现了#error 这个预处理指令.然后回想一下工作, 发现这个指令使用场景还是很多的.比如: 一个项目的模块儿之多,源文件之大,代码之多, ...

随机推荐

  1. [置顶] MapReduce 编程之 倒排索引

    本文调试环境: ubuntu 10.04 , hadoop-1.0.2 hadoop装的是伪分布模式,就是只有一个节点,集namenode, datanode, jobtracker, tasktra ...

  2. idea生成JAVADOC 报java.lang.IllegalArgumentException解决方案[终极]

    idea生成javadoc文档,总是会报  java.lang.IllegalArgumentException     at sun.net.www.ParseUtil.decode(ParseUt ...

  3. window 便笺

    windows的便签很方便人们记录日常工作安排,但是不是所有人都知道如何调用,下面介绍下如何调用windows便签: 1.win + R -->  StikyNot 2.弹出便签界面 3.右击底 ...

  4. 创建、显示和删除保存的用户名和密码(cmdkey)

    创建,显示和删除保存的用户名和密码: cmdkey.exe /add:targetname /user:username /pass:password

  5. SQL Server磁盘I/O性能分析

    SQL Server中的I/O操作类型: 1.对于内存中没有缓存的数据,第一次访问时需要将数据从所在的页面从数据文件中读取到内存中 2.在任何Insert/Update/Delete提交前,SQL S ...

  6. STL之Map的运用

    Map是c++的一个标准容器,她提供了非常好一对一的关系,在一些程序中建立一个map能够起到事半功倍的效果,总结了一些map基本简单有用的操作! 1. map最主要的构造函数:    map<s ...

  7. 关于 ioctl 的 FIONREAD 參数

    ioctl 是用来设置硬件控制寄存器,或者读取硬件状态寄存器的数值之类的.而read,write 是把数据丢入缓冲区,硬件的驱动从缓冲区读取数据一个个发送或者把接收的数据送入缓冲区. ioctl(ke ...

  8. windows平台下php版本问题–VC6/VC9和TS/NTS

    php下载页面中提供了4个下载版本,是vc6/vc9 与 TS/NTS的组合 VC6:legacy Visual Studio 6 compiler,就是使用这个编译器编译的.        VC9: ...

  9. java_泛型方法使用实例

    //提供两种使用情况,第二种情况定义前者是后者的子类-类型通配方式 package ming; import java.util.ArrayList; import java.util.Collect ...

  10. error: /usr/include/objc/objc-class.h: No such file or directory

    When i use the example of ShareKit package,i have come across this error:"error: /usr/include/o ...