Skip to content

define / const / inline / typedef / casting 杂项辨析

一、define vs const

维度#define(宏)const
处理阶段预处理(文本替换,无类型检查)编译期(有类型系统)
类型/作用域无语义,无作用域,全局文本类型安全、遵循作用域/链接规则
内存只是替换;不占数据段(预处理后消失)const 对象存数据段/栈
调试断点/反混淆难常规变量可查
const int vs #define N可能被误用为常量折叠差异在表达式求值可入 switch/模板定长等需常量表达式处(或用 constexpr)

结论:常量优先用 const/constexpr 而非 #define,只有真正的「文本替换/代码宏」才用 define。

二、define vs inline

#define 宏函数inline
类型检查无(文本替换),编译器严格类型检查
求值次数参数表达式可能被多次求值(如 MAX(a++,b) 副作用大)作为函数不求值多次
调试有符号可调试
是否真内联纯文本替换编译器决定(建议性,可能不内联)
规则需小心括号正常函数语义

教训:现代 C++ 用 constexpr/inline/模板替代宏函数避免副作用与类型 bug。

三、typedef vs using(类型别名)/ 与 define 差别

  • typedef int MyInt; 定义类型别名。
  • C++11 using MyInt = int; 更清晰、可模板化(template<...> using)。
  • define 是纯文本替换:不能定义一个真正的类型(无作用域、无检查),如 #define INT int 只是替换为 int,且会全局污染。

四、四种 cast(必考)

cast用途风险
static_cast<T>(expr)编译期:数值类型转换、基类→派生(下行)的多态安全转换依赖静态检查与运行期验证缺省下行不含运行期检查(前提保证正确否则 UB)
dynamic_cast<T*>(expr) / &含多态(需 vtable)的运行期类型转换失败返回 nullptr(指针)/ 抛 bad_cast(引用)
const_cast<T>(expr)去掉/加上 const/volatile去掉后写原 const 对象=UB
reinterpret_cast<T>(expr)位级重解释(指针↔整数等)几乎不检查,最危险

什么时候用哪个

  • 常规安全转换:static_cast
  • 运行时确定是否派生类实例:dynamic_cast(要求基类有虚函数)。
  • 只想去 const:const_cast(如调一个改了但接口本想只读的第三方函数,需谨慎)。
  • 无相关类型强转/底层位视图:reinterpret_cast(几乎只在硬件/序列化)。

问题

  • C 风格 (T)x = 尽可能的组合 cast,不推荐(能偷偷做 reinterpret/const,缺检查)。
  • dynamic_cast 为什么需要 vtable?—— 靠 runtime type 信息 RTTI 查实际类型,vptr 尾部有 type_info(见 oop/vtable)。

五、sizeof / strlen / 数组名

  • sizeof编译期计算类型/表达式所占 字节sizeof(array)=整块)。
  • strlen运行期数到 '\0' 的长度(不含结尾 0)。
  • 数组传给函数形参退化为指针 → sizeof(arr) 变 8(指针),经典坑。
  • sizeof(1==1):C 中 int=4;C++ 中 bool 通常 1 字节 → 结果实现相关(多数 =1),因比较产生 bool。这也是小林那篇的题:C 里 1==1 是 int 4,C++ 里是 bool 通常 1。但注意标准未锁死 bool size,回答「C++ 通常 1,C 是 int 4」最稳。

六、include " " vs < > 与防重

  • #include <xx>:只在系统/标准 include 路径找。
  • #include "xx"先找当前目录/用户路径,找不到再去系统路径。——便于项目内头文件。
  • 防重复包含:#pragma once(MSVC/GCC 都支持,快)或传统 guard:
cpp
#ifndef FOO_H
#define FOO_H
...
#endif
  • 声明 vs 定义放头文件:头文件放声明、模板实现、inline、(C++17 inline 变量);不要放非 inline 的全局变量定义

七、手写 MAX 宏的正确姿势(顺带 sizeof 面试)

cpp
// 正确写法:外层整包括号 + 参数各自括号 + 无副作用
#define MAX(a, b) ((a) > (b) ? (a) : (b))
// 副作用:MAX(++x, y) 会 ++x 两次 —— 所以能用 std::max / constexpr / inline 就别用宏

C++ 面试八股 · VitePress 版