vc之pragma宏的简单应用

vc之pragma宏的简单应用
2007-08-15 21:10
在所有的预处理指令中,#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指令激活或终止该编译程序支持的一些编译功能。例如,对循环优化功能:
#pragma     loop_opt(on)               //     激活
#pragma     loop_opt(off)       //     终止
有时,程序中会有些函数会使编译器发出你熟知而想忽略的警告,如“Parameter     xxx     is     never     used     in     function     xxx”,可以这样:
#pragma     warn     —100               //     Turn     off     the     warning     message     for     warning     #100
int     insert_record(REC     *r)
{     /*     function     body     */     }
#pragma     warn     +100                           //     Turn     the     warning     message     for     warning     #100     back     on
函数会产生一条有唯一特征码100的警告信息,如此可暂时终止该警告。
每个编译器对#pragma的实现不同,在一个编译器中有效在别的编译器中几乎无效。可从编译器的文档中查看。
1 The following pragma causes the linker to search for the EMAPI.LIB library while linking. The linker searches first in the current working directory and then in the path specified in the LIB environment variable:
#pragma comment( lib, "emapi" )
-----------------------------------------------------------------------
2 When the compiler encounters a deprecated symbol, it issues C4995:
void func1(void) {}
void func2(void) {}
int main() {
      func1();
      func2();
      #pragma deprecated(func1, func2)
      func1();      // C4995
      func2();      // C4995
}
----------------------------------------------------------------------
3 The following code fragment uses the message pragma to display a message during compilation:
#if _M_IX86 == 500
#pragma message( "Pentium processor build" )
#endif
-----------------------------------------------------------------------
4 The warning-number-list can contain any warning numbers. Multiple options can be specified in the same pragma directive as follows:
#pragma warning( disable : 4507 34; once : 4385; error : 164 )
This is functionally equivalent to:
#pragma warning( disable : 4507 34 )     // Disable warning messages
                                         //     4507 and 4034.
#pragma warning( once : 4385 )           // Issue warning 4385
                                         //     only once.
#pragma warning( error : 164 )           // Report warning 4164
                                         //     as an error.
Note that the compiler will add 4000 to any warning number that is between 0 and 999.
-----------------------------------------------------------------------
5 This pragma specifies packing alignment for structure, union, and class members,the parameter can only be 1,2,4,8,16,default is 8:
注:如果设置的值比结构体中字节最长的类型还要大,则这个变量(注意仅针对这一个变量)只按照它的字节长度对齐,即不会出现内存浪费的情况。请参见(4)。
(1)
#pragma pack(1)           //每个变量按照1字节对齐
struct A
{
char x;       //aligned on byte boundary 0
int y;        //aligned on byte boundary 1
}a;
sizeof(a)==5
(2)
#pragma pack(2)           //每个变量按照2字节对齐
struct A
{
char x;       //aligned on byte boundary 0
int y;        //aligned on byte boundary 2
}a;
sizeof(a)==6
(3)
#pragma pack(4)           //每个变量按照4字节对齐
struct A
{
char x;       //aligned on byte boundary 0
int y;        //aligned on byte boundary 4
}a;
sizeof(a)==8
(4)
#pragma pack()           //默认,相当于#pragma pack(8) 每个变量按照8字节对齐
struct A
{
char x;       //aligned on byte boundary 0
int y;        //aligned on byte boundary 4
}a;
sizeof(a)==8
但是这里y的大小是4字节,所以不会按照8字节对齐,否则将造成1个int空间的浪费
// 编译器 cl.exe(Visual C++ 6.0)
// 没有做任何优化情况下,编译大小为:16K
// 编译优化后: 1K (用16进制编辑器把尾部的0x00去掉: 712bytes)
#include < windows.h >
#pragma comment(lib,
" kernel32.lib " )

// 作用: 指定节对齐为512字节
#pragma comment(linker, " /align:512 " )

// 作用: 合并节
// 将.data节和.rdata节合并到.text节(代码节)
#pragma comment(linker, " /merge:.data=.text " )
#pragma comment(linker,
" /merge:.rdata=.text " )

// 作用: 指定子系统为windows (和优化无关)
// vc编译器默认是console,会有个黑糊糊的CMD窗口,不好看.用windows就好了
#pragma comment(linker, " /subsystem:windows " )

// 作用: 指定入口函数
// 子系统为windows的默认入口点WinMain和console的默认入口点main,都会引入一段启动stub代码,指定入口函数可去掉之.
#pragma comment(linker, " /ENTRY:main " )


// int WinMain(HINSTANCE current, HINSTANCE prev, LPSTR cmdline, int showcmd)

// 作用: 去掉函数的栈帧代码,纯属吹毛求疵:-)
// 即函数开头的push ebp / mov ebp, esp和结尾的pop ebp / retn
__declspec(naked)
void main()
{
      
// 调用wmp. 这是按套路出牌的方法.
      
// typedef VOID (__stdcall *fnRunDllW)(HWND, HINSTANCE, LPCWSTR, DWORD);
      
// ((fnRunDllW)GetProcAddress(LoadLibrary("msdxm.ocx"), "RunDllW"))(0,0,0,0);

    
// 不按套路出牌,不压入RunDllW的函数参数,直接调用.
       GetProcAddress(LoadLibrary( " msdxm.ocx " ), " RunDllW " )();
      
// 注意此时的堆栈是不平衡的.
      
// 但是通过ExitProcess()退出自身,就不用去考虑平衡了.
       ExitProcess( 0 );
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值