跳转至

运算符

方法速览

结论 内容
优先级主线(高 → 低) 单目 → 算术 → 移位 → 关系 → 位与 → 异或 → 位或 → 逻辑与 → 逻辑或 → 三目 → 赋值 → 逗号
三条铁律 位运算(& ^ |低于比较;&& 高于 ||;赋值、三目、单目右结合
自增自减 前置先加后用,后置先用后加
逻辑 ↔ 离散 ∧ 合取=&&、∨ 析取=||、¬ 非=!;短路:&& 左假停、|| 左真停
位运算三件套 x & (-x) 取最低位 1;x & (x-1) 消最低位 1;x >> k & 1 取第 k 位

运算符优先级(全表)

运算符 说明 结合性
1 () [] . -> 后置 ++ -- 括号、下标、成员
2 前置 ++ -- ! ~ - + * & (类型) sizeof 单目
3 * / % 乘除模
4 + - 加减
5 << >> 移位
6 < <= > >= 关系
7 == != 相等比较
8 & 按位与
9 ^ 按位异或
10 | 按位或
11 && 逻辑与
12 || 逻辑或
13 ? : 三目
14 = += -= *= /= %= <<= >>= &= ^= |= 赋值
15 , 逗号

三条铁律(考试最爱考的三处反直觉):

  • 位运算低于比较x & 1 == 0 实际是 x & (1 == 0)x & 0,恒为 0——判偶必须写 (x & 1) == 0
  • && 高于 ||a && b || c && d = (a && b) || (c && d)
  • 赋值、三目、单目右结合a = b = 5 从右往左算;其余双目运算符一律左结合。

1 << 2 + 3——加法(4 级)高于移位(5 级),先算 2 + 3 = 5,再 1 << 5 = 32

int a = 5, b = 3, c = 4; bool res = a & b || c ^ b && a | c;——按 &^|&&|| 加括号:

1
2
3
4
5
(a & b) || ((c ^ b) && (a | c))
  a & b = 101 & 011 = 001 = 1
  c ^ b = 100 ^ 011 = 111 = 7
  a | c = 101 | 100 = 101 = 5
  1 || (7 && 5)  →  true

自增自减

口诀:前置先加后用,后置先用后加

1
2
3
int a = 5;
int b = a++;   // 后置:b 先拿到 5(先用),a 再变 6(后加)
int c = ++a;   // 前置:a 先变 7(先加),c 再拿到 7(后用)

(循环里的经典位置):

int i = 3, s = 0;
while (i++ < 5) s += i;

逐轮追踪(比较用旧值、进循环体前 i 已加一):

第几轮 比较时的 i 比较后 i s
1 3 < 5 真 4 4
2 4 < 5 真 5 9
3 5 < 5 假 6(仍会加)

循环结束:s = 9i = 6——最后一次比较失败,后置 ++ 照样执行

逻辑运算符与离散数学转换

离散数学 C++ 名称 口诀
∧(合取) && 逻辑与 全真才真
∨(析取) || 逻辑或 见真即真
¬(非) ! 逻辑非 真假互换

转换技巧

  • 德摩根律!(a && b) = !a || !b!(a || b) = !a && !b——非号进去,∧∨ 互换;
  • 分配律a && (b || c) = (a && b) || (a && c)(∨ 对 ∧ 同理);
  • 蕴含p → q 等价于 !p || q(非 p 或 q);
  • 短路求值&& 左边为假时右边不计算|| 左边为真时右边不计算——考试常考“右边那句话执行了几次”。

逗号表达式

  • 形式 a, b, c:从左到右逐个算,整个表达式的值 = 最后一个
  • int x = (1, 2, 3); → x = 3;
  • 注意 int x; x = 1, 2;——赋值(14 级)高于逗号(15 级),等价 (x = 1), 2:x = 1,表达式值 = 2;
  • 函数参数 f(a, b) 里的逗号是分隔符,不是逗号表达式。

三目运算符

  • 形式:条件 ? 真值 : 假值
  • 右结合a ? b : c ? d : e = a ? b : (c ? d : e)——连排三目从右往左套括号。

0 > 1 ? 10 : 2 > 3 ? 20 : 30 = 0 > 1 ? 10 : (2 > 3 ? 20 : 30) → 条件假 → 取 (2 > 3 ? 20 : 30) → 30。

赋值运算符

  • 右结合a = b = c = 5 从右往左:c = 5,b = c(5),a = b(5);
  • 赋值表达式的值 = 左边变量的新值——if (x = 0) 整体为假(值 0),if (x = 2) 整体为真(值 2),经典陷阱;
  • 复合赋值 x <<= 2x = x << 2
  • = 是赋值,== 才是判等——混用不报错但结果全错。

sizeof

两种写法:

  • sizeof(类型名)——类型名必须带括号:sizeof(int)sizeof(double)
  • sizeof 变量——变量可以省括号:sizeof xsizeof(x) 都对;
  • sizeof int语法错误

常用大小(字节):

bool char short int float long long double 指针(64 位)
1 1 2 4 4 8 8 8
  • 数组:int a[10];sizeof(a) = 40,元素个数 = sizeof(a) / sizeof(a[0]) = 10
  • 数组作函数参数退化为指针void f(int a[])sizeof(a) = 8(64 位),不再是数组大小;
  • 字符串字面量:sizeof("abc") = 4(末尾带 \0),strlen("abc") = 3

位运算符及特殊用法

按位基础(以 12、10 为例):

a b a & b a | b a ^ b
1100(12) 1010(10) 1000(8) 1110(14) 0110(6)
  • ~x 按位取反,值为 -x - 1(如 ~12 = -13);
  • 异或三性质:a ^ a = 0a ^ 0 = a、满足交换律结合律——成对出现的数互相抵消,全数组异或后剩落单的那个。

特殊用法速查:

用途 写法
取最低位的 1(lowbit) x & (-x) 12 → 4
消去最低位的 1 x & (x - 1) 12 → 8
判断 2 的幂 (x & (x - 1)) == 0 64 → 是
判奇偶 x & 1 7 → 1(奇)
取第 k 位(从 0 起) (x >> k) & 1 13, k=2 → 1
乘除 \(2^n\) x << n / x >> n 3 << 2 = 12
异或交换 a ^= b; b ^= a; a ^= b; 同一变量会被清零

练习题目

练习 1 · 移位与加减的优先级

题目

表达式 1 << 2 + 3 的值是( )

  • A. \(7\)
  • B. \(32\)
  • C. \(8\)
  • D. \(64\)
答案与解析

答案:B

加法(4 级)高于移位(5 级):先算 2 + 3 = 5,再 1 << 5 = 32

干扰项:A 按“先移位后加”算成 (1 << 2) + 3 = 7;C 是 1 << 3;D 是 1 << 6

练习 2 · 位运算与比较的优先级

题目

int x = 5;,表达式 x & 1 == 0 的值是( )

  • A. 值为 1,判断出 x 是奇数
  • B. 语法错误,无法编译
  • C. 值恒为 0,因为 == 优先级高于 &
  • D. 值为 0,因为 5 是奇数、判偶失败
答案与解析

答案:C

==(7 级)高于 &(8 级):先算 1 == 0 得 0,再 5 & 0 = 0——与 x 的奇偶无关,恒为 0

干扰项:D 结果碰巧也是 0,但理由错(把式子当成了 (x & 1) == 0)。想判偶必须写 (x & 1) == 0

练习 3 · 位运算与逻辑混合链

题目

int a = 6, b = 3, c = 5; bool res = a & b || c ^ b && a | c; 则 res 的值是( )

  • A. true
  • B. false
  • C. \(1\)
  • D. \(0\)
答案与解析

答案:A

优先级 &^|&&||,加括号:

(a & b) || ((c ^ b) && (a | c))

a & b = 110 & 011 = 010 = 2c ^ b = 101 ^ 011 = 110 = 6a | c = 110 | 101 = 111 = 72 || (6 && 7) → true。

干扰项:C 把 bool 当 int 输出——res 的类型是 bool,值为 true

练习 4 · 逻辑值参与算术

题目

表达式 (5 && 3) + (5 || 0) + !5 的值是( )

  • A. \(3\)
  • B. \(7\)
  • C. \(0\)
  • D. \(2\)
答案与解析

答案:D

逻辑运算结果只有 0 和 1:5 && 3 = 1(非零都算真)、5 || 0 = 1!5 = 0;合计 \(1 + 1 + 0 = 2\)

干扰项:B 把 !5 当成 5 参与相加;A 把 5 || 0 当成 5(按位或 5 | 0 = 5 也不是 2)。

练习 5 · 优先级排序

题目

下列运算符按优先级从高到低排列正确的是( )

  • A. + * << < &
  • B. * + << < &
  • C. * + < << &
  • D. << * + < &
答案与解析

答案:B

主线:算术(* 高于 +)→ 移位 → 关系 → 位与。

干扰项:A 把 + 排到了 * 前面(两者同级但顺序颠倒);C 把移位与关系的顺序弄反了(移位 5 级高于关系 6 级);D 把移位排到算术之前。

练习 6 · 后置自增

题目

int a = 5; int b = a++; 执行后 a、b 的值是( )

  • A. \(6\)\(5\)
  • B. \(5\)\(6\)
  • C. \(6\)\(6\)
  • D. \(5\)\(5\)
答案与解析

答案:A

后置先用后加:b 先拿到 5,a 再变 6。

练习 7 · 前置自增

题目

int a = 5; int b = ++a; 执行后 a、b 的值是( )

  • A. \(5\)\(6\)
  • B. \(5\)\(5\)
  • C. \(6\)\(6\)
  • D. \(6\)\(5\)
答案与解析

答案:C

前置先加后用:a 先变 6,b 再拿到 6。与后置对比:a 相同、b 差 1。

练习 8 · 循环条件里的自增

题目

int i = 3, s = 0; while (i++ < 5) s += i; 循环结束后 s 的值是( )

  • A. \(7\)
  • B. \(9\)
  • C. \(10\)
  • D. \(6\)
答案与解析

答案:B

比较用旧值,进入循环体前 i 已加一:第 1 轮 \(3<5\) 真、i=4、s=4;第 2 轮 \(4<5\) 真、i=5、s=9;第 3 轮 \(5<5\) 假退出。s = \(4+5=9\)

干扰项:A = \(3+4\)(把 s += i 理解成加旧值);C 多算一轮。

练习 9 · 混合追踪

题目

int i = 1; int j = i++ + 2; int k = i + ++j; 执行后 k 的值是( )

  • A. \(4\)
  • B. \(5\)
  • C. \(7\)
  • D. \(6\)
答案与解析

答案:D

逐句:i++ + 2 → j = 3,i = 2;++j → j = 4;k = i + j = 2 + 4 = 6

干扰项:C 把第一句当 ++i + 2(j = 4,k = 2 + 5 = 7)。

练习 10 · 离散符号求值

题目

x = truey = falsez = true,以下逻辑运算表达式值为真的是( )

  • A. (x ∧ y) ∨ z
  • B. x ∧ y ∧ z
  • C. (x ∨ y) ∧ ¬z
  • D. ¬x ∧ z
答案与解析

答案:A

逐项代入 x=T, y=F, z=T:A = (T∧F)∨T = T;B 含 F 为 F;C = T∧¬T = F;D = F∧T = F。

干扰项:C 的 (x ∨ y) 虽为真,但被 ∧ ¬z 拖成假——析取见真即真、合取见假即假。

练习 11 · 德摩根律

题目

!(a && b) 等价于( )

  • A. !a && !b
  • B. a || b
  • C. !a || !b
  • D. !(a || b)
答案与解析

答案:C

德摩根律:非号分进去,∧∨ 互换——¬(a ∧ b) = ¬a ∨ ¬b

干扰项:A 是 ¬a ∧ ¬b(对应 !(a || b),把两条律弄反了)。

练习 12 · 德摩根律(嵌套非)

题目

!(x || !y) 等价于( )

  • A. !x || y
  • B. x && !y
  • C. !x && !y
  • D. !x && y
答案与解析

答案:D

外层非进去:¬(x ∨ ¬y) = ¬x ∧ ¬(¬y) = ¬x ∧ y——非非抵消。

干扰项:C 忘了 ¬y 还要再取一次反。

练习 13 · 蕴含转换

题目

命题“如果 p 那么 q”(p → q)用 C++ 逻辑表达式写出,正确的是( )

  • A. p || !q
  • B. !p || q
  • C. !p && q
  • D. p && !q
答案与解析

答案:B

蕴含等价于“非 p 或 q”:p 假时前件不成立、整体为真;p 真时只看 q。

干扰项:A 把 p、q 的位置写反——p || !q 恰好是 q → p(反方向的蕴含);D 是 p → q 为的唯一情形(p 真且 q 假)。

练习 14 · 分配律

题目

a && (b || c) 等价于( )

  • A. (a && b) || (a && c)
  • B. (a || b) && (a || c)
  • C. a || (b && c)
  • D. (a && b) || c
答案与解析

答案:A

∧ 对 ∨ 满足分配律:a ∧ (b ∨ c) = (a ∧ b) ∨ (a ∧ c)

干扰项:B 是 ∨ 对 ∧ 的分配律(它等价于 a || (b && c));D 漏乘第二个分支。

练习 15 · 短路求值

题目

int i = 0; int r = (i != 0) && (10 / i > 1); 执行后( )

  • A. r = 1
  • B. 程序因除以零崩溃
  • C. r = 0,右侧 10 / i 不执行
  • D. 编译错误
答案与解析

答案:C

&& 左边 (i != 0) 为假 → 短路,右边不计算r = 0,不会除零。

干扰项:B 不知道短路保护;若换成 ||(左边真短路)或把左边写反,右边才会执行。

练习 16 · 逗号表达式的值

题目

int x = (1, 2, 3); 执行后 x 的值是( )

  • A. \(1\)
  • B. \(2\)
  • C. \(3\)
  • D. \(6\)
答案与解析

答案:C

逗号表达式从左到右逐个求值,值 = 最后一个:x = 3。

干扰项:D 把三个数加了起来(逗号不是加法)。

练习 17 · 赋值与逗号混合

题目

int x; x = 1, 2; 执行后 x 的值与整个表达式的值是( )

  • A. x = 2,表达式值 2
  • B. x = 1,表达式值 2
  • C. x = 1,表达式值 1
  • D. x = 2,表达式值 1
答案与解析

答案:B

赋值(14 级)高于逗号(15 级):(x = 1), 2——x = 1,逗号表达式取最后一个,值 = 2。

干扰项:A 以为逗号先算——想让 x = 2 必须写 x = (1, 2);

练习 18 · 三目嵌套(右结合)

题目

int x = 1 > 0 ? 10 : 2 > 3 ? 20 : 30; x 的值是( )

  • A. \(10\)
  • B. \(20\)
  • C. \(30\)
  • D. 语法错误
答案与解析

答案:A

三目右结合1 > 0 ? 10 : (2 > 3 ? 20 : 30) → 条件真 → 直接取 10,右半根本不看。

干扰项:B 按左结合误算 ((1 > 0 ? 10 : 2) > 3) ? 20 : 3010 > 3 真 → 20——左结合不是 C++ 语义。

练习 19 · 三目参与算术

题目

(5 > 3 ? 2 : 1) + (1 > 2 ? 10 : 20) 的值是( )

  • A. \(22\)
  • B. \(12\)
  • C. \(30\)
  • D. \(11\)
答案与解析

答案:A

左半:5 > 3 真 → 2;右半:1 > 2 假 → 20;合计 \(2 + 20 = 22\)

干扰项:B 把右半取了真值分支(10);D 两边都取了假值分支。

练习 20 · 连环赋值的结合性

题目

int a, b, c; a = b = c = 5; 的求值顺序是( )

  • A. 从左到右,先 a 后 b
  • B. 三者同时赋值
  • C. 未定义,视编译器而定
  • D. 从右到左,先 c 后 b 再 a
答案与解析

答案:D

赋值右结合a = (b = (c = 5))——c 先得 5,赋值表达式的值再依次传给 b、a。

干扰项:C 与“求值顺序未指定”混淆——右结合是语言规定的。

练习 21 · 赋值当判等

题目

int x = 3; if (x = 0) printf("A"); else printf("B"); 输出是( )

  • A. A
  • B. B
  • C. 无输出
  • D. 死循环
答案与解析

答案:B

x = 0赋值:x 变 0,整个表达式的值 = 0 = 假 → 走 else 输出 B。若写 if (x = 2) 则值为 2 = 真,恒走 if。

干扰项:A 把 = 看成了 ==x == 0 为假,同样走 else,但那是判等)。

练习 22 · sizeof 两种写法

题目

下列 sizeof 的用法中错误的是( )

  • A. sizeof(int)
  • B. int x; sizeof x
  • C. sizeof int
  • D. int x; sizeof(x)
答案与解析

答案:C

类型名必须带括号,sizeof int 语法错误;变量两种写法都对(B、D 等价)。

练习 23 · 数组元素个数

题目

int a[10];sizeof(a) / sizeof(a[0]) 的值是( )

  • A. \(10\)
  • B. \(40\)
  • C. \(4\)
  • D. \(1\)
答案与解析

答案:A

sizeof(a) = 4 × 10 = 40 字节,除以单个元素 4 字节 = 元素个数 10。

干扰项:B 忘了除;C 只算了单个元素。

练习 24 · sizeof 与 strlen

题目

sizeof("abc")strlen("abc") 的值分别是( )

  • A. \(3\)\(3\)
  • B. \(4\)\(4\)
  • C. \(3\)\(4\)
  • D. \(4\)\(3\)
答案与解析

答案:D

sizeof全部字节,含末尾的 '\0' → 4;strlen 数到 '\0' 为止的字符个数 → 3。

练习 25 · 数组参数退化

题目

64 位环境下,void f(int a[]) { /* 此处 sizeof(a) */ }sizeof(a) 的值是( )

  • A. \(40\)
  • B. \(8\)
  • C. \(4\)
  • D. \(10\)
答案与解析

答案:B

数组作函数参数时退化为指针sizeof 得到的是指针大小:64 位下 8 字节。

干扰项:A 以为还带着数组的 40 字节进来。

练习 26 · 三种按位运算求值

题目

(12 & 10) + (12 | 10) + (12 ^ 10) 的值是( )

  • A. \(22\)
  • B. \(30\)
  • C. \(28\)
  • D. \(32\)
答案与解析

答案:C

1100 & 1010 = 1000(8);1100 | 1010 = 1110(14);1100 ^ 1010 = 0110(6);合计 \(8 + 14 + 6 = 28\)

练习 27 · lowbit

题目

x & (-x)(x = 12)的值是( )

  • A. \(4\)
  • B. \(8\)
  • C. \(12\)
  • D. \(1100\)
答案与解析

答案:A

x & (-x)最低位的 1\(12 = 1100_2\),最低位的 1 在权值 4 处 → 4。这是树状数组的核心操作。

干扰项:B 是消最低位后的结果(x & (x-1));D 把二进制当值了。

练习 28 · 判断 2 的幂

题目

下列 x 中,使 (x & (x - 1)) == 0 成立的是( )

  • A. \(12\)
  • B. \(48\)
  • C. \(64\)
  • D. \(96\)
答案与解析

答案:C

x & (x-1) 消去最低位的 1;结果为 0 说明只有一个 1,即 2 的幂。\(64 = 1000000_2\) 只有一个 1:\(64 \& 63 = 0\)\(12 \& 11 = 8\)\(48 \& 47 = 32\)\(96 \& 95 = 64\) 均非 0。

练习 29 · 取第 k 位

题目

(13 >> 2) & 1 的值是( )

  • A. \(0\)
  • B. \(3\)
  • C. \(4\)
  • D. \(1\)
答案与解析

答案:D

\(13 = 1101_2\),右移 2 位得 \(11_2 = 3\),再 & 1 取最低位 → 1——即 13 的第 2 位(从 0 数起)是 1。

干扰项:B 忘了 & 1(那是 13 >> 2 本身)。

练习 30 · 异或交换的陷阱

题目

a ^= b; b ^= a; a ^= b; 三句执行后的效果是( )

  • A. 交换 a、b 的值,任何情况下都安全
  • B. 交换 a、b 的值,但 a、b 是同一个变量时会把它清零
  • C. 把 a、b 都清零
  • D. 没有任何作用
答案与解析

答案:B

利用 a ^ a = 0 逐步抵消可完成交换;但当两个参数是同一个变量时,第一句 a ^= a 就把它清成 0,之后再也恢复不回来。

干扰项:A 忽略了同变量情形(自己和自己 swap 时翻车)。

练习 31 · 异或找落单数

题目

数组 \(\{2, 3, 5, 3, 2\}\) 全部元素异或起来,结果是( )

  • A. \(5\)
  • B. \(0\)
  • C. \(2\)
  • D. \(10\)
答案与解析

答案:A

异或满足交换律结合律,且 a ^ a = 0:两个 2、两个 3 互相抵消,只剩 5。

干扰项:B 是全部成对时的结果(没有落单数);D 把全部求和了。

练习 32 · 移位组合

题目

(7 >> 1) << 1 的值是( )

  • A. \(7\)
  • B. \(3\)
  • C. \(14\)
  • D. \(6\)
答案与解析

答案:D

7 >> 1 = 3(除 2 下取整,丢掉最低位 1),再 << 1 = 6——右移再左移等于清掉最低位

干扰项:A 以为移出去的位还能回来;C 方向反了(那是 7 << 1)。

练习 33 · 复合位赋值

题目

int x = 3; x <<= 2; x |= 1; 执行后 x 的值是( )

  • A. \(7\)
  • B. \(13\)
  • C. \(12\)
  • D. \(9\)
答案与解析

答案:B

x <<= 2x = 3 << 2 = 12\(1100_2\));x |= 1 把最低位置 1 → \(1101_2 = 13\)

干扰项:C 是只做第一步的结果;A = 3 | 100(漏了移位后的高位)。

历年真题

2019 年 · 第 2 题

题目

二进制数 11 1011 1001 011101 0110 1110 1011 进行逻辑与运算的结果是( )。

  • A. 01 0010 1000 1011
  • B. 01 0010 1000 0001
  • C. 01 0010 1000 0011
  • D. 01 0010 1001 0011
答案与解析

答案:C

按位与:同 1 为 1。逐位相与 0011101110010111 & 0001011011101011 = 0001001010000011,按 4 位分组即 01 0010 1000 0011

2020 年 · 第 3 题

题目

x = truey = truez = false,以下逻辑运算表达式值为真的是( )。

  • A. (y ∨ z) ∧ x ∧ z
  • B. x ∧ (z ∨ y) ∧ z
  • C. (x ∧ y) ∧ z
  • D. (x ∧ y) ∨ (z ∨ x)
答案与解析

答案:D

代入 x=T, y=T, z=F:A、B 都含 ∧ z 被拖成假;C = T∧T∧F 假;D = (T∧T) ∨ (F∨T) = T ∨ T = 真。

易错

合取 ∧ 见假即假——选项里只要挂着一个假变量 z,整条链就断了;析取 ∨ 见真即真,救得回来。

2025 年 · 第 2 题

题目

在 C++ 中,执行 int x = 255; cout << (x & (x - 1)); 后,输出的结果是?( )

  • A. \(255\)
  • B. \(254\)
  • C. \(128\)
  • D. \(0\)
答案与解析

答案:B

\(255 = 11111111_2\)\(254 = 11111110_2\),按位与 = \(11111110_2 = 254\)。结论:x & (x - 1) 消去最低位的 1

2025 年 · 第 7 题

题目

假设 \(a, b, c\) 都是布尔变量,逻辑表达式 (a && b) || (!c && a) 的值与下列哪个表达式始终相等?( )

  • A. a && (b || !c)
  • B. (a || !c) && (b || !c) && (a || a)
  • C. a && (!b || c)
  • D. !(!a || !b) || (a && !c)
答案与解析

答案:C

原式提取公因子 a:(a && b) || (a && !c) = a && (b || !c)(分配律)——与 A 恒等;B 再用 ∨ 对 ∧ 的分配律可化回同一式;D 用德摩根律 !(!a || !b) = a && b 化回原式;C 的 !b || c 与原式的 b || !c 真值表不符。

易错

化简方向:先提公因子(分配律),再用德摩根律去非号——逐个选项化到最简再比对,别凭眼缘。

易错小结

  • 位运算低于比较x & 1 == 0 恒为 0,判偶要写 (x & 1) == 0
  • 移位低于加减1 << 2 + 3 = 32 不是 7;
  • 后置 ++ 在比较失败时也执行while (i++ < 5) 退出后 i 已经多加了一次;
  • 短路会跳过右边:除法、赋值写在 &&/|| 右边时可能根本不执行;
  • = 不是 ==if (x = 0) 恒假、if (x = 2) 恒真;
  • sizeof 类型必须带括号,变量可省;数组传参退化为指针后 sizeof 是指针大小;
  • x & (x-1) 消最低位 1、x & (-x) 取最低位 1——判 2 的幂、lowbit 别混用。