C++ 宏定义和const区别 C++ 预处理替换与编译期类型检查【理论】
发布时间 - 2026-01-30 00:00:00 点击率:次宏定义在预处理阶段纯文本替换,无类型、无作用域、不参与编译检查;const变量具类型和地址,可调试;constexpr是现代C++推荐的编译期常量方案,类型安全且支持编译期计算。
宏定义在预处理阶段就被替换了,根本没机会参与类型检查
预处理器只做纯文本替换,#define PI 3.14159 后,所有 PI 都被无差别替换成 3.14159,连括号都不加。它不占内存、没有作用域、不经过编译器语义分析——所以 sizeof(PI) 是非法的(预处理后变成 sizeof(3.14159),但这是字面量,不是对象),而 auto x = PI; 中的 x 类型由字面量推导为 double,但这个过程发生在替换之后,和宏本身无关。
常见错误现象:
-
#define MAX(a,b) a > b ? a : b导致MAX(i++, j++)展开成i++ > j++ ? i++ : j++,副作用执行两次 -
#define FLAG 1和int FLAG = 2;
在同一作用域不报错(宏先被删了),但逻辑混乱
- 调试时无法对宏名设断点,IDE 里看不到“变量”定义位置
const 变量是真正的编译期常量(满足条件时),有类型、有地址、能进符号表
const double PI = 3.14159; 声明了一个具有 double 类型的左值,有内存地址(除非被优化掉),支持取址 &PI,可参与模板推导、用作数组维度(若为字面量常量表达式)、能出现在 switch 的 case 中(前提是是 constexpr 或整型字面量常量表达式)。
但注意:不是所有 const 都是编译期常量:
-
const int x = rand();—— 运行期初始化,只是不可修改,不能用于模板非类型参数 -
const int y = 42;—— 满足常量表达式要求,等价于constexpr int y = 42;(C++17 起隐式 constexpr) -
extern const int z;—— 外部链接,定义在别处,编译器通常无法在本翻译单元确认其值,不能用于需要常量表达式的地方
用 constexpr 替代宏才是现代 C++ 的正确姿势
宏该退场了。真正需要编译期常量的地方,优先用 constexpr:
-
constexpr double PI = 3.1415926535;—— 类型安全、可调试、支持sizeof、能用于所有常量表达式上下文 -
constexpr int square(int x) { return x * x; }—— 函数也能编译期求值,宏函数做不到泛型和重载 -
template—— 模板参数必须是常量表达式,struct Array { int data[N]; }; Array错(PI是double),但Array对(返回int)
宏只剩少数场景还必要:条件编译(#ifdef)、头文件卫士(#pragma once 或 #ifndef XXX_H)、字符串化(#__FILE__)、连接符(# 和 ##)——这些是预处理器专属能力,constexpr 无法替代。
调试和符号信息差异直接影响开发体验
你用 gdb 调试时,print PI 会提示 “no symbol”,因为宏早已消失;而 print PI_const(对应 const double PI_const = ...)能正常显示值、类型、地址。IDE 的跳转、重命名、查找引用等功能对宏完全失效,但对 const 和 constexpr 变量完全支持。
容易被忽略的一点:const 变量默认内部链接(static),而宏没有链接属性概念——这意味着多个源文件里定义同名 const int x = 1; 不会链接冲突,但宏定义重复可能导致意外覆盖或警告。反过来,如果真需要外部链接的编译期常量,得显式写 extern constexpr int x = 1; 并在某处定义。
# 处理器
# c++
# switch
# 区别
# 作用域
# print
# Static
# Array
# 常量
# define
# 整型
# const
# auto
# extern
# 字符串
# 预处理器
# 无类型
# int
# double
# Struct
# 泛型
# symbol
# 对象
# ide
# 都是
# 这是
# 多个
# 才是
# 出现在
# 也能
# 两次
# 并在
# 跳转
# 等功能
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
nginx修改上传文件大小限制的方法
EditPlus中的正则表达式实战(6)
如何自定义建站之星网站的导航菜单样式?
Laravel怎么在Controller之外的地方验证数据
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
javascript如何操作浏览器历史记录_怎样实现无刷新导航
米侠浏览器网页背景异常怎么办 米侠显示修复
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
高端智能建站公司优选:品牌定制与SEO优化一站式服务
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
Python文件异常处理策略_健壮性说明【指导】
详解jQuery停止动画——stop()方法的使用
高防服务器租用首荐平台,企业级优惠套餐快速部署
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
Swift开发中switch语句值绑定模式
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
javascript日期怎么处理_如何格式化输出
油猴 教程,油猴搜脚本为什么会网页无法显示?
使用C语言编写圣诞表白程序
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
VIVO手机上del键无效OnKeyListener不响应的原因及解决方法
高端建站如何打造兼具美学与转化的品牌官网?
如何在 Pandas 中基于一列条件计算另一列的分组均值
Laravel队列任务超时怎么办_Laravel Queue Timeout设置详解
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
JS经典正则表达式笔试题汇总
如何快速查询域名建站关键信息?
详解Huffman编码算法之Java实现
iOS验证手机号的正则表达式
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
如何快速搭建FTP站点实现文件共享?
如何自定义建站之星模板颜色并下载新样式?
Bootstrap整体框架之JavaScript插件架构
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
如何用5美元大硬盘VPS安全高效搭建个人网站?
Laravel如何构建RESTful API_Laravel标准化API接口开发指南
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程
Bootstrap CSS布局之列表
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
浅谈redis在项目中的应用
详解Android中Activity的四大启动模式实验简述
Laravel distinct去重查询_Laravel Eloquent去重方法
如何快速重置建站主机并恢复默认配置?


