#pragma指令的用法

简介:

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。 
其格式一般为: #Pragma Para 
其中Para 为参数,下面来看一些常用的参数。 

(1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗 
口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: 
#Pragma message(“消息文本”) 
当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 
当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法 
#ifdef _X86 
#Pragma message(“_X86 macro activated!”) 
#endif 
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_ 
X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了 
。 

(2)另一个使用得比较多的pragma参数是code_seg。格式如: 
#pragma code_seg( ["section-name"[,"section-class"] ] ) 
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。 

(3)#pragma once (比较常用) 
只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。 

(4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。 
有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。 

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

(6)#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 也支持如下格式: 
#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 comment(...) 
该指令将一个注释记录放入一个对象文件或可执行文件中。 
常用的lib关键字,可以帮我们连入一个库文件。

 

#pragma pack(1) 作用

主要用来设置结构定义的字节对齐方式,比如是单字节对齐,双字节对齐等,比如如果是双字节对齐,那么结构的成员变量的地址必须是2的整数倍,这就造成了字节补齐,但是提高了访问速度。单字节呢,就是没有补齐,成员变量的地址是连续的,其他依次类推,通常是4,8等。通常用于网络传输数据,特别是传输整个结构时,必须采取单字节对齐,这样才可以直接把结构地址,以及结构长度,作为Send的参数发送整个结构,否则只能依次发送结构的成员,要不然会出现结构解释的差异。 

另外,在Project->Setting->C/C++->Code Generation->Struct member alignment中可以设置结构的对齐方式。  

传输结构时和pack无关,只要Recv端定义的结构和Send方一样就没问题了。 
pack多用于Hook程序,比如Hook Api技术,因为需要硬编码,所以必须将结构 
压缩,将内容补齐! 
比如: 
ASM_STRUCT{ 
BYTE bJmp; 
DWORD dwDes; 
}a; 
如果不用Pack时,编译为: 
a.bJmp = 0xEB; // jmp的编码 
a.dwDes = 0x00410123; // jmp 0x00410123 
不用pack的话,内存内容为 0xEB XX XX XX 23 01 41 00 // 共8BYTE 
其中XX为不定值,用pack后 0xEB 23 01 41 00 // 共5BYTE 
这样,在Hook时运行这些指令,就必须用#parama pack(1) // 1 BYTE方式对齐。

如果直接把结构地址,以及结构长度,作为Send的参数发送整个结构,难道不需要pack吗?请教verybigbug()兄

不需要。 
send(struct, sizeof(struct));就可以了,如果两个程序都没有pack的话, 
相同的结构体在接收数据时就没有问题。必须保证两边的pack都是一样才行。 
我在写socket的程序(SDK方式)时送结构就从来不用pack的。 
只在写Hook Api时才用pack(1)。  

 

#pragma comment(lib, "ws2_32") 是什么意思 ???

.就相当于你将ws2_32.lib包含到工程中去。这样你就可以使用DLL接口函数了

 

#pragma data_seg 是什么意思??

用#pragma data_seg建立一个新的数据段并定义共享数据,其具体格式为: 

#pragma data_seg ("shareddata") 

HWND sharedwnd="NULL";//共享数据 

#pragma data_seg()     // 再windows 核心编程思想中有很多地方用到。

目录
相关文章
技术宅之---用手机实现“移动网关”
本文假定读者已知道内网穿透相关认知。 或许你用过花生壳、frp、ngrok、teamviewer等穿透工具,今天要给大家介绍的是smarGate(https://github.com/lazy-luo/smarGate) 1、samrGate是什么? 官方命名为“移动网关”,通过手机客户端将位于内网的服务端网络进行按需暴露。
3932 0
|
8月前
|
机器学习/深度学习 传感器 编解码
全球降水测量 全球降水测量(GPM)07 版
全球降水测量(GPM)07版是由NASA和JAXA合作的国际卫星任务,提供每三小时一次的全球雨雪观测数据。该数据集使用IMERG算法整合多颗卫星的微波和红外数据,提供高精度的降水量估算。GPM 07版涵盖2000年6月至2025年1月的数据,适用于气象预报、洪水预警等领域。数据以二进制格式提供,分辨率约为11公里,时间分辨率为半小时。NASA免费提供这些数据供公众使用。
340 22
|
7月前
YOLOv11改进策略【Head/分割头】| 结合CVPR-2024 中的DynamicConv 动态卷积 改进分割头, 优化模型(独家改进)
YOLOv11改进策略【Head/分割头】| 结合CVPR-2024 中的DynamicConv 动态卷积 改进分割头, 优化模型(独家改进)
535 8
|
小程序 JavaScript
Taro@3.x+Vue@3.x+TS开发微信小程序,使用轮播图
本文介绍了使用 Taro 和 Vue 创建轮播组件的两种方法:一是通过 `<swiper>` 实现,二是利用 Nut UI 的 `<nut-swiper>` 组件实现。
396 2
Taro@3.x+Vue@3.x+TS开发微信小程序,使用轮播图
|
应用服务中间件 Linux 网络安全
windows+linux环境下nginx部署环境
windows+linux环境下nginx部署环境
237 1
|
11月前
|
安全 网络安全 网络虚拟化
Cisco-三层交换机实现VLAN间路由
Cisco-三层交换机实现VLAN间路由
224 0
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
577 30
|
机器学习/深度学习 数据采集 算法
【Python机器学习专栏】自动化特征选择与优化的实践
【4月更文挑战第30天】特征选择在机器学习中至关重要,能降低模型复杂度,提高泛化能力和避免过拟合。本文介绍了自动化特征选择的三种方法:过滤法(如SelectKBest)、包装法(如RFE)和嵌入法(如随机森林)。通过结合这些方法,可实现特征优化,包括数据预处理、初步筛选、模型训练与评估、特征优化和结果验证。自动化特征选择能提升模型性能,适应不同数据集和任务需求,为机器学习项目提供坚实基础。
492 0
|
Java Spring
springboot异常处理之404
springboot异常处理之404
510 1
springboot异常处理之404