在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、预编译概述 1.1 预编译定义
1.2 预编译功能 预编译指令通常用于文件包含,宏定义,编译控制(包括:条件编译、编译器警告配置、字节对齐、放置注释、上报消息等等),预编译还有一些更深层次的使用方法,下文将会介绍,综述预编译功能主要为:
二、常用预编译指令
2.1 文件包含 #include "xxx.h" // 优先搜索当前目录 #include <yyy.h> // 优先搜索系统目录 PS:使用后定义符号,解决重复包含或者使用#pragma once
2.2 宏定义 2.2.1 标识宏定义 #ifndf _XXX_H_ // 常用于头文件标识定义 #define _XXX_H_ // header file content …… #endif
#undef _YYY_H_ // 如果需要也可取消一个标识定义 不过头文件中一般时不要要取消定义的,在调试( #define _DEBUG_ )等其他用途中常会使用此功能;
2.2.2 标识或功能宏 还有一些常用的宏定义,用于定义常量或这完成某种功能,但要注意宏定义的形式,不然可能产生意想不到的效果,举例: #define PI 3.14 // define const variable #define Cube(n) (n)*(n)*(n) // calculate n's cube /* may work as above macro, but may cause unexpected result */ #define Cube_2(n) n*n*n
举个栗子,对比使用宏Cube和Cube_2,我们就能发现区别: int num = 8 + 2; volume = Cube(num); // 展开结果为:(8 + 2)*(8 + 2)*(8 + 2) volume2 = Cube_2(num); // 展开结果为:8 + 2*8 + 2*8 + 2 因此计算结果的大不相同;
2.2.3 ##运算符 ##运算符用于把参数连接到一起。预处理程序把出现在##两侧的参数合并成一个符号。看下面的例子: #define NUM(a,b,c) a##b##c #define STR(a,b,c) a##b##c main() { printf("%d\n",NUM(1,2,3)); printf("%s\n",STR("aa","bb","cc")); } 最后程序的输出为: 123 aabbcc
2.3 编译控制 2.3.1 #line改变行号和文件 使用语法,#line number ["filename"],举例: #line 1000 "123.cpp" cout << "行号:" <<__LINE__ << "\n文件名:" << __FILE__ << endl; 此时输出结果为: 行号:1000 文件名:123.cpp 此编译命令常用与调试,辅助定位代码问题
2.3.2 #error上报编译错误 在某些情况下,控制编译抛出错误,举个栗子: #ifdef XXX ... #error "XXX has been defined" #else
2.3.3 #pragma系列
命令格式: #pragma warning( warning-specifier : warning-number-list [; warning-specifier : warning-number-list...]) #pragma warning( push[ ,n ] ) // 保存警告信息的现有的警告状态 [,把全局警告等级设定n]. #pragma warning( pop ) // 弹出警告信息,在入栈和出栈之间所作的一切改动取消 举个栗子: /* 不显示4507和34号警告信息,4385号警告只显示一次,164号警告作为错误 */ #pragma warning( disable : 4507 34; once : 4385; error : 164 )
#pragma pack(x) // x is int number struct A { char x; double y; int z; }a; sizeof(a)==13; // if x = 1 sizeof(a)==14; // if x = 2 sizeof(a)==16; // if x = 4 sizeof(a)==24; // if x = 8,default 相当于#pragma pack()
#pragma comment( lib, "xxapi" ) // 动态导入 xxapi.lib
#pragma deprecated 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 }
#pragma message("This is a test msg.")
三、预编译进阶使用 C++使用“头文件-源文件”的编译模型,每个源文件为一个编译单元,产生一个obj文件,然后所有obj被link到一起,生成exe文件。
在较大的系统软件中,有数以万的源文件,而每个头文件可能会包含数十甚至上百个头文件, 在每一个编译单元,这些头文件都会被从硬盘读进来一遍,然后被解析一遍,无数头文件的重复load与解析以及密集的磁盘操作,严重拖慢了程序的编译速度。
针对这个问题,有多种优化方式 [ref: C++ 预编译解析 ], 这里我们只看预编译头,是如何在这个问题上做出贡献的:
四、预编译元编程 此处不探讨此功能,参见:
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论