ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

现代c++第2.2章 条件编译

现代c++第2.2章 条件编译 C 里所谓“条件编译宏定义预处理命令”其实主要涉及三件事宏定义#define/#undef、条件编译#if / #ifdef / #ifndef / #elif / #else / #endif以及文件包含#include。它们都在编译之前由预处理器处理本质上是文本替换和文本选择不是 C 语言层面的类型、作用域或函数调用。1. 宏定义#define和#undef对象式宏#definePI3.14159#defineBUFFER_SIZE1024预处理器会把后面代码中出现的PI替换成3.14159BUFFER_SIZE替换成1024。现代 C 更推荐这样写constexprdoublePI3.14159;constexprintBUFFER_SIZE1024;因为constexpr/const有类型、有作用域调试时也能看到名字而宏只是文本替换出错时可能只提示替换后的值。函数式宏#defineMAX(a,b)((a)(b)?(a):(b))看起来像函数但仍然是文本替换。它有两个常见坑#defineSQUARE(x)x*xintrSQUARE(51);// 展开成 5 1 * 5 1结果是 11正确写法要给参数和整体都加括号#defineSQUARE(x)((x)*(x))但即使这样如果参数有副作用仍然危险MAX(i,j)// i 可能被求值多次所以现代 C 更推荐用inline函数或模板函数替代函数式宏。取消宏#undefDEBUG表示之后DEBUG不再被视为已定义宏。2. 条件编译#if / #ifdef / #ifndef / #elif / #else / #endif条件编译的作用是根据宏是否定义、表达式是否为真决定哪些代码参与编译。基本形式#ifdefDEBUGprintf(debug mode\n);#endif如果DEBUG被定义过这段代码会被编译否则会被预处理器直接丢弃。#ifndefDEBUGprintf(release mode\n);#endif如果DEBUG没有被定义就编译这段代码。等价写法是#ifdefined(DEBUG)#if!defined(DEBUG)#ifdef等价于#if defined(...)#ifndef等价于#if !defined(...)。多分支条件#ifdefined(_WIN32)// Windows 平台代码#elifdefined(__linux__)// Linux 平台代码#else// 其他平台#endif#if后面可以写整型常量表达式也可以配合defined()做组合判断。数值判断#defineVERSION2#ifVERSION2// 新版本逻辑#elifVERSION1// 旧版本逻辑#endif注意#if里只能使用编译期常量表达式不能用普通变量。3. 头文件保护防止重复包含这是条件编译最经典、也最重要的用途。#ifndefMY_HEADER_H#defineMY_HEADER_H// 头文件内容#endif第一次包含时MY_HEADER_H未定义预处理器进入并定义它第二次包含时#ifndef MY_HEADER_H为假整个头文件内容被跳过从而避免重复定义。也可以用#pragmaonce很多编译器支持但不是 C 标准强制要求。4. 编译时传入宏在 Linux 终端编译时可以用-D传入宏g-DDEBUG-omain main.cpp这等价于在源文件开头写了#defineDEBUG所以代码里可以这样写#ifdefDEBUGstd::coutdebug info\n;#endif不传-DDEBUG时调试代码不会进入最终程序。5. 常见预定义宏编译器会自动提供一些宏宏含义__cplusplusC 标准版本__FILE__当前源文件名__LINE__当前行号__DATE__编译日期__TIME__编译时间_WIN32Windows 平台通常定义__linux__Linux 平台通常定义例如#if__cplusplus201703L// C17 及以上才编译#endif6. 现代 C 的使用建议场景老式写法更推荐写法常量#define N 100constexpr int N 100;简单函数#define MAX(a,b) ...inline/template函数枚举常量#define RED 1enum class头文件保护#ifndef#ifndef或#pragma once平台/调试开关#ifdef/#if仍然常用也就是说宏用来做“编译期开关”和“头文件保护”仍然很常见但用来表示常量、函数、枚举时现代 C 更推荐用语言特性替代。一个完整小例子#includeiostream#ifndefMAX_SIZE#defineMAX_SIZE100#endifintmain(){#ifdefined(DEBUG)std::coutDebug mode, MAX_SIZE MAX_SIZE\n;#elsestd::coutRelease mode\n;#endifreturn0;}编译时g-DDEBUG-omain main.cpp ./main会输出调试信息不加-DDEBUG时调试分支根本不会参与编译。
返回列表