预处理指令 #pragma 的一些用法

1. 格式

  #pragma parameter.

2. parameter选项

-#pragma message("消息内容"):用于编译过程中在输出编译消息的窗口中显示相应的信息

 eg.#ifdef  COMPUTER_A

  #pragma message("sizeof int is 4 bytes.")

  #endif

  上述指令的作用就是在编译阶段检查 “COMPUTER_A”是否被定义,如果定义了,int的大小为4字节。

  这对于在控制源代码版本的时候,检查某些宏是否被设置了很有用。

-#pragma code_seg(["section_name"[,"section_class"]]):用于设置程序中函数代码存放的代码段,进行驱动开发的时候会使用到。

-#pragma once:用于保证头文件只被编译一次(用的比较多)

  与#ifndef #define #endif的比较: 

  #pragma once 是编译相关的,现在基本每个编译器都有了这个定义,不存在兼容问题

  #ifndef #define #endif 是C/C++语言相关的,是C/C++语言中的宏定义,也就是说在所有支持C++语言的编译器上都是有效的,但是如果程序需要跨平台使用,最好使用#pragma once.

  另#ifndef方式依赖宏文件名不能冲突,可以保证同名文件不会被包含多次,也可以保证内容相同的两个文件不会被同时包含,这就要求对宏名的定义一定不能相同;

  而#pragma once方式由编译器保证同一个文件不会被包含多次,这里“同一个文件”指物理上的同一个文件,而不是内容名称都相同而绝对路径不同的两个文件,这带来的缺点就是不能保证有多个拷贝的头文件只被包含一次。

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

  BCB(Borland C++ Builder)通过预编译头文件来加快连接是的速度,但是如果同时对所有头文件进行预编译,可能会占用较大的内存空间,所以可以使用这个选项排除一些头文件。

  但有时程序段间可能存在依赖关系,比如说程序段A依赖程序段B,那么B应该在A之前得到编译,这可以通过#pragma startup来指定编译优先级,如果使用了#pragma package(smart_init),BCB会根据优先级的大小先后编译。

-#pragma resource “filename”:把filename指定的资源文件添加到工程。

-#pragma warning:用于给出告警信息

  例1 #pragma warning(disable:4507 34;once:4385;error:164)

  含义:不显示4507和34号警告信息;

      只报告一次4385警告信息;

      把164号警告信息当作一个错误。

-#pragma comment:将一个注释记录放入一个对象文件或可执行文件中

-#pragma pack( [show]|[push|pop][,identifier],n] ):数据对其

  说明:调用pack不指定参数时,n将被设置成默认值。一旦减小数据类型的对其标准,直接效果是占用的内存变少、整体性能下降。、

  show:显示当前字节对其标准,将以 warning message的方式显示;

  push:将当前字节对其标准数值进行压栈操作,这里的栈是The internal compiler stack,并设置当前的字节对其标准为n,如果n没有指定,则将当前栈顶的记录压栈;

  pop:从The internal compiler stack中删除最顶端的记录。如果没有指定n,则出栈后栈顶的记录为新的字节对其标准;如果指定了n,则n成为新的字节对其标准;如果指定了identifier,则从 internal compiler stack中pop直到identifier被找到,然后pop出            identifier,同时设置字节对其标准为当前栈顶的记录;如果指定的identifier不存在,则pop操作被忽略。

  identifier:当同push一起使用时,赋予当前被压入栈中的记录一个名称;当同pop一起使用时,同pop中所述。

  n:指定字节标准的大小,以字节为单位,缺省值为8,合法值有:1,2,4,8,16。

  基本概念:

  1.数据类型自身的对齐值:就是基本数据类型的自身对齐值(也就是占用的字节数,如int一般为4个字节)。

  2.指定对齐值:#pragma pack (n) 指定对齐值n。

  3.结构体或者类的自身对齐值:其数据成员中自身对齐值最大的那个值。

  4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中的那个值。

  重要规则:

  1. 复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个类型的地址相同;

  2. 每个成员分别对齐,即每个成员按自己的方式对齐,并最小化长度;规则就是每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐;

  3. 结构、联合或者类的数据成员,第一个放在偏移为0的地方;以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度两个中比较小的那个进行;

      也就是说,当#pragma pack指定的值等于或者超过所有数据成员长度的时候,这个指定值的大小将不产生任何效果;

  4. 复杂类型(如结构)整体的对齐<注意是“整体”>是按照结构体中长度最大的数据成员和#pragma pack指定值之间较小的那个值进行;这样在成员是复杂类型时,可以最小化长度;

  5. 结构整体长度的计算必须取所用过的所有对齐参数的整数倍,不够补空字节;也就是取所用过的所有对齐参数中最大的那个值的整数倍,因为对齐参数都是2的n次方;这样在处理数组时可以保证每一项都边界对齐

  例1:

  #pragma pack(2)                                                      #pragma pack(4)

  struct B                        struct  C

  {                            {

    char  b;                        char  b;

           int    a;                         int    a;

           short  c;                         short  c;

  }                           }

  针对上面两个列子,对于结构体B:

  数据成员b自身的对其值为1,指定对其值为2,故有效对其值为1(min(2,1)),假设存放地址为0x0000;

  数据成员a自身对其值为4,指定对其值为2,故有效对其值为2(min(2,4)),存放地址的起始地址%2==0,故存放地址应该是:0x0002-0x0005

  数据成员c自身对其值为2,指定对其值为2,故有效对其值为2(min(2,2)),存放地址的起始地址%2==0,故存放地址应该是:0x0006-0x0007

  总的内存消耗为8。

  结构体B自身对其值为4(max(1,2,4)),指定对其值为2,故结构体B有效对其值为2(min(2,4)),总内存消耗8%2==0,不需要补充。

  对于结构体C:

  数据成员b自身的对其值为1,指定对其值为4,故有效对其值为1(min(4,1)),假设存放地址为0x0000;

  数据成员a自身对其值为4,指定对其值为4,故有效对其值为4(min(4,4)),存放地址的起始地址%4==0,故存放地址应该是:0x0004-0x0007

  数据成员c自身对其值为2,指定对其值为4,故有效对其值为2(min(2,4)),存放地址的起始地址%2==0,故存放地址应该是:0x0008-0x0009

  总的内存消耗为10。

  结构体B自身对其值为4(max(1,2,4)),指定对其值为4,故结构体B有效对其值为4(min(4,4)),总内存消耗10%4!=0,需要最少补充2个字节,故总的内存消耗为12字节。

  故:sizeof(B)=8,  sizeof(C)=12.

原文地址:https://www.cnblogs.com/haisence/p/3683371.html