#pragma 预处理指令详解

本文详细介绍了C/C++编译预处理指令#pragma的各种用途,包括message、code_seg、once、hdrstop等参数的应用场景,并深入探讨了内存对齐问题及#pragmapack指令的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在所有的预处理指令中,#pragma 指令可能是最复的了,它的作用是编译器的状或者是指示编译器完成一些特定的作。

    #pragma指令每个编译出了一个方法,在保持与CC++言完全兼容的情况下,出主机或操作系统专有的特征。

 

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

    其格式一般: #pragma  para 

    其中para参数,下面来看一些常用的参数。 

 

(1)message 参数

    message参数是我最喜的一个参数,它能编译信息出窗口中出相的信息,

这对于源代信息的控制是非常重要的。其使用方法 

    #pragma  message("消息文本") 

    编译器遇到条指令就在编译输出窗口中将消息文本打印出来。 

    当我在程序中定多宏来控制源代版本的候,我自己有可能都会忘有没有正确的些宏,

可以用条指令在编译候就检查。假希望判断自己有没有在源代的什么地方定_X86个宏,

可以用下面的方法:

    #ifdef  _X86 

    #pragma  message("_X86  macro  activated!") 

    #endif 

    _X86个宏以后,用程序在编译时就会在编译输出窗口里"_86  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 )    //  450734号警告信息 

    #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  )   

    段代的最后,重新保存所有的警告信息(包括470547064707) 

 

 

(7)#pragma  comment(...) 

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

常用的lib字,可以帮我们连入一个文件。如:

    #pragma  comment(lib, "comctl32.lib")

    #pragma  comment(lib, "vfw32.lib")

    #pragma  comment(lib, "wsock32.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实现不同,在一个编译器中有效在编译器中几乎无效。可从编译器的文档中看。

 

 

—— #pragma pack 内存对齐问题

 

    实际算机系统对基本型数据在内存中存放的位置有限制,它会要求些数据的首地址的是某个数k

(通常它48)的倍数,就是所的内存对齐,而k被称为该数据型的对齐模数(alignment modulus)

 

    Win32平台下的微C编译(cl.exe for 80x86)在默情况下采用如下的对齐规则:

    任何基本数据T对齐模数就是T的大小,即sizeof(T)比如double(8)

就要求该类型数据的地址8的倍数,而char型数据(1)可以从任何一个地址开始。

 

    Linux下的GCC奉行的是另外一套规则(料中得,并未验证,如错误请指正):

    任何2大小(包括节吗?)的数据(比如short)对齐模数是2,而其它所有超2的数据

(比如long,double)都以4为对齐模数。

 

    ANSI C定一种型的大小是它所有字段的大小以及字段之或字段尾部的填充区大小之和。

填充区就是了使构体字段足内存对齐要求而外分配给结构体的空。那么构体本身有什么对齐要求

有的,ANSI C构体型的对齐要求不能比它所有字段中要求最格的那个松,可以更格。

 

 

如何使用c/c++中的对齐选项

 

    vc6中的编译选项 /Zp[1|2|4|8|16] /Zp1表示以1节边对齐,相的,/Zpn表示以n节边对齐

n节边对齐的意思是,一个成的地址必安排在成的尺寸的整数倍地址上或者是n的整数倍地址上,取它中的最小

也就是:

    min ( sizeof ( member ),  n)

 

    实际上,1节边对齐也就表示了构成没有空洞。

    /Zpn选项用于整个工程的,影响所有的参与编译构。

    要使用选项,可以在vc6中打开工程属性c/c++选择Code Generation,在Struct member alignment可以选择

 

    专门针对某些构定使用对齐选项,可以使用#pragma pack编译指令:

 

(1) #pragma  pack( [ n ] )

 

    指令指定构和合成对齐。而一个完整的转换单元的构和合的对齐/Zp 选项设置。

对齐pack编译指示在数据层设置。该编译指示在其出后的第一个构或生效。

该编译指示无效。

    当你使用#pragma  pack ( n ) , n 1248 16

    第一个构成之后的每个构成都被存在更小的成员类型或n 界限内。

如果你使用无参量的#pragma  pack, 构成/Zp 指定的缺省/Zp 值为/Zp8

 

(2) 编译器也支持以下增:

    #pragma  pack( [ [ { push | pop } , ] [ identifier, ] ] [ n] )

 

    若不同的件使用pack编译指示指定不同的对齐, 法允你把程序一个独的转换单元。

push参量的pack编译指示的每次出将当前的对齐到一个内部编译器堆中。

    编译指示的参量表从左到右取。如果你使用push, 当前被存起来;

如果你出一个n , 该值将成新的。若你指定一个标识, 即你定一个名称,

则该标识符将和个新的的值联系起来。

 

    一个pop参量的pack编译指示的每次出都会索内部编译器堆栈顶,并且使该值为新的对齐值

如果你使用pop参量且内部编译器堆是空的,则紧值为命令行定的, 并且将生一个警告信息。

若你使用pop且指定一个n, 该值将成新的。若你使用p o p 且指定一个标识,

所有存在堆中的将从, 直到找到一个匹配的标识, 个与标识符相关的也从中移出,

并且标识符入之前存在的新的。如果未找到匹配的标识,

将使用命令行置的, 并且将生一个一警告。缺省对齐为8

 

   pack编译指示的新的增功能文件, 确保在遇到该头文件的前后的

是一的。

 

(3) 内存对齐

    vc6对齐方式不受构成员对齐选项的影响。它是保持对齐,而且对齐4节边界上。

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值