运算符与类型转换
更新时间:2026-08-27。本文是
languages/cpp/主题入门层第 6 篇。算术、比较、逻辑运算符 C 和 C++ 基本一致,但类型转换上 C++ 走出了关键一步:用static_cast/const_cast/reinterpret_cast取代 C 的强制转换。本篇讲运算符速览、C 风格转换的隐患、四种 C++ cast 的适用场景。
本文要回答的问题
- C++ 的运算符和 C 有什么异同?
- 为什么说 C 风格的强制转换
(int)x有隐患? - 四种
xxx_cast分别什么时候用?
一、运算符速览(和 C 基本一致)
| 类别 | 运算符 | 说明 |
|---|---|---|
| 算术 | + - * / % | 整数除法截断、% 取模 |
| 比较 | == != < <= > >= | 结果为 bool |
| 逻辑 | && || ! | 短路求值 |
| 位 | & | ^ ~ << >> | 位运算(与 C 相同) |
| 赋值 | = += -= *= /= %= | 复合赋值 |
| 自增自减 | ++ -- | 前缀/后缀区别 |
| 三目 | ?: | 条件表达式 |
&& 和 || 的短路求值是重点:a && b 如果 a 为假就不再求 b,a || b 如果 a 为真就不再求 b。新手常利用这一点写:
if (ptr != nullptr && ptr->value > 0) { ... }ptr 为空时第二个条件根本不会执行,天然避免空指针解引用——这是 C/C++ 都有的经典技巧。
二、隐式转换与它的坑
C++ 会自动做"安全"的类型转换(隐式转换):
double d = 3.14;
int n = d; // 隐式:double → int,小数部分被截断(n == 3)隐式转换发生在:
- 算术运算中类型提升(
int和double混算,int转double); - 赋值时窄化(
double赋给int); - 函数实参匹配。
坑点:隐式窄化会静默丢精度。上一篇讲的 {} 初始化会拦这种转换;普通赋值 int n = d; 不拦。数值混合运算的符号问题(有符号/无符号)也是经典坑,详见 C 语言的有符号与无符号篇,C++ 行为完全一致。
三、C 风格强制转换为什么有隐患
C 的 (int)x 强制转换,C++ 兼容但不推荐:
// C 风格
int n = (int)d; // double → int
const char* p = (const char*)buf; // 任意指针互转问题:
- 意图不明:
(int)x到底是"数值转换"还是"位模式重解释"?编译器不知道你要干嘛,读者也不知道; - 可检索性差:大工程里搜
(int)形式困难; - 不该转的也转:C 风格转换可以无视 const、无视类型安全,一次全放开——出错时没有任何提示。
四、C++ 四种 cast
C++11 引入四个显式转换运算符,每种只管一件事:
| 运算符 | 用途 | 例子 |
|---|---|---|
static_cast<T>(x) | 常规类型转换:数值、向上转型 | static_cast<int>(d) |
const_cast<T>(x) | 去掉/添加 const | const_cast<char*>(cs) |
reinterpret_cast<T>(x) | 位模式重解释(指针/整数互转) | reinterpret_cast<uintptr_t>(p) |
dynamic_cast<T>(x) | 多态类型安全向下转型(需 RTTI) | 继承篇详讲 |
double d = 3.99;
int n = static_cast<int>(d); // n == 3,显式且意图明确
const char* cs = "...";
// char* p = static_cast<char*>(cs); // 编译错误:不能去 const
char* p = const_cast<char*>(cs); // 必须用 const_cast
uintptr_t addr = reinterpret_cast<uintptr_t>(&d); // 指针 → 整数什么时候用哪个:90% 的情况是 static_cast(数值转换、类型安全的向上转换);去 const 用 const_cast(尽量避免);指针与整数互转、类型完全不同的指针互转用 reinterpret_cast(极危险,明确知道在干嘛才用);多态向下转型用 dynamic_cast(继承与多态篇展开)。
C++ 之父 Bjarne 说过类似的话:强制转换说明设计有问题——尽量让类型转换自然发生,非要转时用对应 cast 把"你在干什么"写清楚。
五、C++ cast 与 C 对照
| 场景 | C 写法 | C++ 写法 | 安全性 |
|---|---|---|---|
| double → int | (int)d | static_cast<int>(d) | 编译期检查 |
| 去 const | 直接转 | const_cast<T> | 意图明确 |
| 指针 ↔ 整数 | (int)p | reinterpret_cast<uintptr_t>(p) | 警告显式 |
| 多态向下转型 | 手动判断 | dynamic_cast<T> | 运行期检查 |
C++ 不是禁止转换,而是把转换分类、把意图显式化——出问题时编译器和读者都能更快发现。
六、与本站主线衔接
reinterpret_cast在二进制协议、底层驱动里的用法,与 L5 ELF 与 ABI 相关;- 数值混合运算的精度陷阱(浮点 vs 整数、溢出),见 L3 数值与溢出;
- C 的类型转换(隐式/显式),见 C 语言类型转换。
一句话总结
C++ 运算符与 C 一致,但类型转换显式化:static_cast(常规转换)、const_cast(去 const)、reinterpret_cast(位重解释)、dynamic_cast(多态向下转型)四种 cast 取代 C 的万能 (T)x,让"你打算干什么"一目了然;能自然转换就不强转,强制转换本身就是设计信号。
上一篇:std::string 入门 下一篇:字符串流 stringstream