运算符
CIN 的运算符集合与 C 高度相似, 但有三处必须记住的差异: / 恒为浮点除法、 * / & 没有指针含义、位运算只接受整数。
优先级表
按优先级从低到高 (越靠后结合越紧):
| 优先级 | 运算符 | 说明 | 适用类型 |
|---|---|---|---|
| 1 | ?: | 三目 cond ? a : b (短路, 结果可赋值) | bool 条件 |
| 2 | || | 逻辑或 (短路) | bool (任意类型可转 bool) |
| 3 | && | 逻辑与 (短路) | bool |
| 4 | | | 位或 | int/bool |
| 5 | ^ | 位异或 | int/bool |
| 6 | & | 位与 | int/bool |
| 7 | == != | 相等比较 | 全部 |
| 8 | < > <= >= | 关系比较 | int/float |
| 9 | << >> | 左移 / 算术右移 (保留符号) | int/bool |
| 10 | + - | 加减, + 兼作字符串拼接 | int/float/string |
| 11 | * / % | 乘除取模 (/ 浮点除, % 仅整数) | int/float |
| 12 | ! ~ -x ++x --x | 逻辑非 / 位取反 / 负号 / 前缀自增自减 | — |
| 13 | x++ x-- [] . f() | 后缀自增自减 / 下标 / 成员 / 调用 | — |
| 14 | = += -= *= /= %= &= |= ^= <<= >>= | 赋值 (右结合, 左值只求值一次) | int/float 左值 |
不确定就加括号
CIN 不做隐式的“整数化”提升来迎合直觉, 混用类型时加括号 + 显式转换最省心:
int q = idiv(a + b, c) // 整数除法
float r = (a + b) / c // 浮点除法
string s = "n = " + (a + b) // 先算数, 再拼字符串算术运算
| 表达式 | 结果 | 说明 |
|---|---|---|
7 / 2 | 3.5 | / 恒为浮点除法 |
idiv(7, 2) | 3 | 整数除法 (内建, 向零截断) |
idiv(-7, 2) | -3 | 向零截断, 不是向下取整 |
7 % 3 | 1 | 取模仅支持整数 |
7.5 % 2 | 运行期错误 | Float modulo not supported |
2 + 3 * 4 | 14 | * 优先于 + |
-x | 取负 | 一元负号 |
需要“商的整数部分”时一律用
idiv(a, b); 需要浮点结果时用/(见 内建函数)。
位运算
& | ^ ~ << >> 只接受整数 (int / bool / 整数字面量), 复合写法为 &= |= ^= <<= >>=:
int a = 0b1100 & 0b1010 // 8 (1000)
int b = 0b1100 | 0b1010 // 14 (1110)
int c = 0b1100 ^ 0b1010 // 6 (0110)
int d = 1 << 4 // 16
int e = -16 >> 2 // -4 (算术右移, 保留符号)
int f = ~0 // -1 (位取反)
int m = 0xFF
m &= 0x0F // 15
m <<= 4 // 240
m >>= 2 // 60<<左移在低位补 0;>>是算术右移 (符号位扩展), 对负数保持符号;- 移位量按低 6 位取模 (
& 63), 即x << 64等价x << 0; - 对
float/string使用位运算会报Bitwise operator ... requires integer operands。
比较与逻辑
bool ok = (x > 0) && (x < 100) // 短路: 左侧为假时右侧不求值
bool bad = (s == "") || (n != 0) // 左侧为真时右侧不求值==/!=对整数、浮点、bool、struct 按值比较;<><=>=用于 int/float;!是逻辑非 (布尔取反),~才是位取反, 两者不可混用。
字符串不要用 == 比较内容
string 变量持有的是指针, == 比较的是这个 64 位值而不是字符串内容。 实测: "ab" + "c" == "abc" 为 false (两者地址不同), 而 strcmp(a, b) == 0 为 true。 判断字符串内容相等请一律使用内建 strcmp(a, b) == 0 (见 字符串)。
短路求值有副作用
&& / || 的右侧可能根本不执行, 因此不要依赖右侧的函数调用一定发生:
if (i < n && arr[i] > 0) { ... } // i >= n 时不会读 arr[i], 安全复合赋值与自增自减
int x = 10
x += 5 // 15
x -= 3 // 12
x *= 2 // 24
x /= 5 // 4.8 -> 4 (截断)
x %= 3 // 1
x <<= 3 // 8
x &= 0b110 // 0
int y = ++x // 前缀: 先自增, 表达式值是新值
int z = x-- // 后缀: 表达式值是旧值, 再自减- 赋值/复合赋值/自增自减都是表达式, 可以参与运算, 例如
int y = ++x * 2; - 对
float自增自减每次 ±1.0, 复合赋值同样支持 (f += 0.5); %=与位运算复合赋值仅整数;- 字符串支持
+=: 右侧任意可字符串化的值都会被追加 (见下节); 其余-=*=/=等对字符串仍报Cannot apply '-=' to type: string。
字符串拼接
+ 任意一侧为 string 时, 另一侧会被自动字符串化 (int / float / bool / char):
println("Age: " + 18) // Age: 18
println("PI: " + 3.14) // PI: 3.14
println("OK: " + true) // OK: true
println("n = " + (2 + 3)) // n = 5 (先算数, 结果字符串化)
string s = "a" + "b" + "c" // 连续拼接 (每步产生新的堆块)+= 用于原地追加, 是累积输出/构建文本时最常用的写法:
string log = ""
log += "[info] start" // 追加字符串
log += " n="
log += 42 // 数字自动字符串化 -> " n=42"
println(log) // [info] start n=42== 比较指针, 不是内容
拼接产生的是新堆块, 所以 s == "abc" 比较的是两个指针值, 几乎总是 false。 判断内容请用 strcmp(s, "abc") == 0, 判空用 strlen(s) == 0 (见 字符串)。
拼接会产生新的堆块; 循环里大量拼接字符串会持续占用堆空间, 必要时改用
codecin/lib/conv/src/conv.cin的c_repeat等工具函数 (见 标准库参考)。
三目表达式
string status = (score >= 60) ? "pass" : "fail"
int sign = (x < 0) ? -1 : 1- 只求值被选中的那一侧 (短路);
- int/float 混用时按 float 提升;
- 两侧同为
string时才允许字符串结果, 否则请先显式转换; - 结果可以出现赋值语句左侧或嵌套在其它表达式中, 但深层嵌套建议拆开写。
常见错误
| 错误信息 | 原因 | 修正 |
|---|---|---|
Unsupported int operator: xx | 对整数用了不支持的运算 | 使用 + - * / % & | ^ << >> |
Float modulo not supported | 对浮点用了 % | 先取整或改用 idiv |
Bitwise operator ... requires integer operands | 对 float/string 用位运算 | 位运算只用于 int/bool |
Type mismatch ... | 比较/拼接操作数类型不兼容 | 显式转换后再运算 |
| 结果与预期差 1 | 用了 / 而不是 idiv | 整数除法用 idiv(a, b) |