c++ #Pragma
2023-01-30 本文已影响0人
AArman
//定义了_X86 宏以后,应用程序在编译时就会在编译输出窗口里显示message
#ifdef _X86
#Pragma message(“_X86 macro activated!”); // 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来
#endif
#pragma code_seg( ["section-name"[,"section-class"] ] ); //它可以设置程序中函数代码存放的代码段
#pragma once; //只要在头文件的最开始加入这条指令就可以保证头文件被编译一次
#pragma hdrstop; //表示预编译头文件到此为止,后面的头文件不进行预编译。BCB 能够预编译头文件以加快连接的速度,但若是全部头文件都进行预编译又可能占太多磁盘空间,因此使用这个选项排除一些头文件。
#pragma comment(lib, "user32.lib"); //将user32.lib 库文件加入到本工程
#pragma warning(disable:4507 34); // 不显示4507 和34 号警告信息
#pragma warning(once:4385); // 4385 号警告信息仅报告一次
#pragma warning(error:164); // 把164 号警告信息做为一个错误
#pragma warning(push); //保存全部警告信息的现有的警告状态
#pragma warning(push, n); //保存全部警告信息的现有的警告状态,而且把全局警告等级设定为n
#pragma warning(pop); //向栈中弹出最后一个警告信息,在入栈和出栈之间所做的一切改动取消
#pragma once 和 #ifndef _x_h 区别
-
ifndef _x_h
-
ifndef 的方式受C/C++语言标准支持。它不仅可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含
-
ifndef受C/C++语言标准的支持,不受编译器的任何限制;
- 缺点:如果宏名称一样时,编译器会提示找不到声明
-
-
pragma once
- 由编译器提供支持,同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。
- 不必担心宏名冲突问题
- 缺点:如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含
pragma pack
- 机器的位数
- 计算机一次能处理数据的最大位数称为该机器的位数,位数跟电脑的CPU有关。
64位的机器一次最多从内存中读取8字节
32位的机器一次最多从内存中读取4字节
- 计算机一次能处理数据的最大位数称为该机器的位数,位数跟电脑的CPU有关。
- 对齐系数
- 每个特定平台上的编译器都有自己的默认“对齐系数”
默认的结构体对齐系数,取决于成员中最大的变量所占的字节数,按照最大变量所占的字节数进行对齐,(sizeof(struct))
Q : 默认的对齐方式,可能造成CPU读取变量效率低,或者内存浪费。因为64位机器一次最多读取8位, 在c++中可以通过预编译命令,来调整对齐系数
数。进而调整结构体的存储方式
-
pragma pack(n)
- n=1,2,4,8,16来改变这一系数,其中的n就是要指定的“对齐系数”
- 对齐规则:
- 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack 指定的数值和这个数据成员自身长度中,比较小的那个进行
- 结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行
如果 n 大于等于该变量所占用的字 节数,那么偏移量必须满足默认的对齐方式
如果 n 小于该变量的类型所占用 的字节数,那么偏移量为 n 的倍数,不用满足默认的对齐方式
- 结构的约束条件:
如果 n 大于所有成员变量类型所占用的字节数,那么结 构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必须为 n 的倍数
如果 #pramga pack(n) 中的n大于结构体成员中任何一个成员所占用的字节数,则该n值无效。编译器会选取结构体中最大数据成员的字节数为基准
#pragma pack(n); //作用:C编译器将按照n个字节对齐
#pragma pack() //作用:取消自定义字节对齐方式
#pragma pack(push, n); //作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为n个字节对齐
#pragma pack(pop); //作用:恢复对齐状态
- 在网络协议编程的作用
- 在网络协议编程中,经常会处理不同协议的数据报文
- 一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦
- 利用pragma pack特性,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。避免通讯两边因设备原因造成对齐系数不同。如果已知两边的对齐方式相同,加不加没有影响
#pragma pack(1) // 按照1字节方式进行对齐
struct TCPHEADER
{
short SrcPort; // 16位源端口号
short DstPort; // 16位目的端口号
int SerialNo; // 32位序列号
int AckNo; // 32位确认号
unsigned char HaderLen : 4; // 4位首部长度
unsigned char Reserved1 : 4; // 保留6位中的4位
unsigned char Reserved2 : 2; // 保留6位中的2位
unsigned char URG : 1;
unsigned char ACK : 1;
unsigned char PSH : 1;
unsigned char RST : 1;
unsigned char SYN : 1;
unsigned char FIN : 1;
short WindowSize; // 16位窗口大小
short TcpChkSum; // 16位TCP检验和
short UrgentPointer; // 16位紧急指针
};
#pragma pack()