阅读下面的程序:
01int x = 12, y = 10; 02int z = x & y;
已知 ,,z 的值是( )。
考点:按位与(A1)。
(A1)考点:按位与 & 对每一位做与运算——两位都为 1,结果位才为 1。
解析:,,逐位相与:,即 。
排除法:A 选 2 是把 12 和 10 按十进制数位逐个"与";B 选 14 是 12 | 10 按位或的结果;D 选 6 是 12 ^ 10 按位异或的结果。
阅读下面的程序:
01int a = 12 | 10; // 先按位或 02int b = a & 6; // 再按位与
执行后 b 的值是( )。已知 ,,。
考点:按位或(A2)。
(A2)考点:按位或 | 两位只要有一个为 1 结果位就是 1;& 与 | 可以组合成多步运算。
解析:第一步 ;第二步 ,,。
排除法:A 选 4 是 时把 位算丢了;C 选 14 只算了第一步、忘了按位与;D 选 8 只取了 的最高位。
阅读下面的程序:
01int a = 7, b = 3; 02a = a ^ b; 03b = a ^ b; 04a = a ^ b;
执行后 a 和 b 的值分别是( )。
考点:异或交换(A3)。
(A3)考点:异或三步交换利用 ——某数与另一个数异或两次等于自己。
解析:设 。第一步 a = 7 ^ 3;第二步 b = a ^ b = 7 ^ 3 ^ 3 = 7;第三步 a = a ^ b = (7 ^ 3) ^ 7 = 3。最终 ,完成交换。
排除法:A 是"没发生交换"的直觉答案;B、C 是把中间某值重复赋给两个变量造成的同值结果。
阅读下面的程序:
01int x = 7; 02int y = ~~x;
执行后 y 的值是( )。
考点:双重取反(A4)。
(A4)考点:双重取反回到原值——,因为 ,再取反一次:。
解析:~7 = -8,~(-8) = 7(),所以 ~~7 = 7。两次取反恢复原值。
排除法:B 选 -7 把取反当成了求相反数;C 选 -8 只取反了一次;D 选 6 把 误记成了 。
阅读下面的程序,其中 A = 12(二进制 1100)表示集合 ,B = 10(二进制 1010)表示集合 :
01int A = 12, B = 10; 02int un = A | B; // 并集 03int in = A & B; // 交集
执行后 un 和 in 的值分别是( )。
考点:位掩码集合运算(A5)。
(A5)考点:一个整数可以用二进制位表示集合——第 位为 1 表示元素 在集合中;并集用 |、交集用 &、补集用 ~。
解析: 表示 , 表示 。并集 ();交集 ()。
排除法:A 把并集和交集的结果对调;C 的交集算成了异或( 才是异或);D 直接取了原值。
阅读下面的程序(按常见编译器的补码行为):
01int x = 1 << 31;
执行后 x 的值是( )。
考点:左移溢出符号位(A6)。
(A6)考点:int 只有 32 位,1 << 31 把 1 移进了符号位——按常见编译器的补码行为结果是负数(严格说左移越界属于未定义行为,写代码时应主动避免)。
解析: 左移 31 位得到位模式 1000...0000(1 后面 31 个 0),按补码解释这是 (int 的最小值)。
排除法:A 选 0 以为溢出会清零;B 选 2147483648 是无符号思维(int 装不下这个正数);D 选 -1 把溢出与取反混淆。
阅读下面的程序:
01int x = 5, y = -3; 02bool same = (x ^ y) >= 0;
执行后 same 的值是( )。
考点:异或判同号(A7)。
(A7)考点:异号的两数符号位不同,异或后符号位为 1、结果为负数;同号则符号位为 0——所以 (x ^ y) >= 0 可以判断两数是否同号。
解析: 的符号位是 0, 的符号位是 1,,x ^ y 的符号位为 1,是负数,所以 same = false(两数异号)。
排除法:A 选 true 只算了数值部分、忘了符号位;B 该写法完全合法;C 把 bool 的结果和整数 1 混为一谈(false 转 int 才是 0)。
阅读下面的程序:
01int x = 3; 02x = x << 4;
执行后 x 的值是( )。
考点:左移倍增(B1)。
(B1)考点:x << k 等价于 (不溢出时)。
解析:。
排除法:A 选 12 把移位量当成了乘数();C 选 24 只乘了 ;D 选 96 多乘了一个 2。
阅读下面的程序:
01int x = 23; 02x = x >> 2;
执行后 x 的值是( )。
考点:右移整除(B2)。
(B2)考点:对非负整数,x >> k 等价于 向下取整。
解析:。二进制上看:,右移 2 位去掉末尾两位得 。
排除法:A 选 11 只右移了 1 位;B 选 6 是四舍五入的结果;C 选 4 把 看成了 。
阅读下面的程序:
01int a = -7 >> 1; 02int b = -7 / 2;
执行后 a 和 b 的值分别是( )。
考点:负数右移与除法(B3)。
(B3)考点:负数右移是"向负无穷取整"(算术右移),而 C++ 的整数除法是"向零取整"——两者对负数的结果不同。
解析: 右移 1 位得 (相当于 );而 (向零取整)。记住:负数的 >> 和 / 不一样。
排除法:B 以为右移与除法结果相同;C 以为除法也向负无穷取整;D 把两个结果都记反。
阅读下面的程序:
01int x = 1 << 10;
执行后 x 的值是( )。
考点:1<<n 与 2^n(B4)。
(B4)考点:1 << n 得到 ,这是二进制里最重要的构造手段。
解析:。记忆锚点: 是计算机里最常用的"千",约 1KB。
排除法:A 选 20 把 << 10 当成了 再 ;B 选 1000 用十进制约数记混;D 选 2048 是 。
阅读下面的程序:
01int a = 5; 02a ^= a; 03a ^= a;
执行后 a 的值是( )。
考点:异或交换自坑(B5)。
(B5)考点:异或交换的陷阱——如果两次异或作用在同一个变量上,a ^= a 会把自己清零,再异或也救不回来。
解析:第一次 a ^= a 后 ;第二次 a ^= a 是 。结果是 0。异或"两次还原"要求两次异或的另一个操作数相同,而这里第二次异或时 a 已经变成 0 了。
排除法:A 选 5 是"异或两次还原"的误用;C 选 10 当成了加法;D 选 -5 把 ^ 当成了 ~。
阅读下面的程序:
01int s = 0; 02for (int i = 0; i < 5; i++) 03 s += 1 << i;
执行后 s 的值是( )。
考点:循环构造低位掩码(B6)。
(B6)考点:循环累加 1 << i 就是在拼低位全 1 的位模式——这是构造掩码的标准做法。
解析:,二进制 11111,正好是低 5 位全 1,等于 。
排除法:B 选 16 只加了最后一项;C 选 30 漏加了 ;D 选 32 多算了一项 。
阅读下面的程序:
01int a = 5; 02int b = ~a;
执行后 b 的值是( )。
考点:取反与负数(C1)。
(C1)考点:补码体系下 ——取反和求相反数是两回事,差 1。
解析: 的每一位翻转后按补码解释是 。验证:,而 恒等于 (全 1),所以 。
排除法:A 选 5 认为取反无效果;B 选 -5 把取反当成了求相反数(漏了 );D 选 6 把符号搞反。
阅读下面的程序:
01int x = 7; 02int y = ~x + 1;
执行后 y 的值是( )。
考点:取反加一求相反数(C2)。
(C2)考点:——补码里求相反数的标准做法是"取反加一"。
解析: 是 (),再加 1 得 ,正是 的相反数。
排除法:B 选 7 认为两次操作抵消;C 选 6 只算了 忘记加一;D 选 -8 忘了加一。
阅读下面的程序:
01int x = -8; 02x = x >> 2;
执行后 x 的值是( )。已知 的补码末字节为 1111 1000。
考点:负数右移符号扩展(C3)。
(C3)考点:负数右移时高位补符号位 1(符号扩展),移出的低位丢弃——右移 位相当于除以 向下取整,结果仍是负数。
解析: 的补码是 1111 1000,右移 2 位:高位补两个 1、低位移出两个 0,得 1111 1110,按补码解释是 。
排除法:A 选 -32 把右移当成了左移();B 选 2 是"高位补 0"的逻辑右移思路(正数右移才补 0);C 选 -4 只右移了 1 位。
阅读下面的程序:
01int x = -2, y = 3; 02int z = x & y;
执行后 z 的值是( )。已知 的补码末四位为 1110,。
考点:负数按位与(C4)。
(C4)考点:负数按补码存储,按位运算在补码位模式上进行——先把负数写成二进制再算。
解析: 的补码是 ...1110,,逐位与得 0010,即 。
排除法:A 选 1 用 想当然;C 选 -2 认为与正数做 & 结果还是负数;D 选 0 以为符号不同的数与运算必为 0。
用 8 位补码表示整数时,能表示的最小整数是( )。
考点:补码最小值(C5)。
(C5)考点:8 位补码的范围是 ——负数比正数多一个,因为 0 占了正数区。
解析:8 位共 个位模式,补码把 1000 0000 分配给 ,0111 1111 分配给 ,其余对称,所以最小是 。
排除法:B 选 -255 把无符号的 256 当成了对称范围;C 选 -127 是按原码思路(符号位 + 7 位数值)的经典错解;D 选 -256 把范围总数当成了最小值。
阅读下面的程序:
01int x = -1; 02x = x << 1;
对这段代码,下列说法正确的是( )。
考点:负数左移未定义(C6)。
(C6)考点:负数左移属于未定义行为——C++ 标准没有规定结果,不同编译器或优化级别可能给出不同答案,写代码时应主动避免。
解析:-1 << 1 在标准中是未定义行为(左移要求左侧操作数为非负)。实测常见编译器会得到 ,但依赖这个结果是不安全的,考试以外写代码应避免。
排除法:A 选 -2 是常见编译器的实际行为,但标准未保证,不能当作"正确答案";B 同理;D 语句本身能通过编译,只是行为未定义。
阅读下面的程序:
01int x = 9; 02int a = x & 0; 03int b = x ^ 0;
执行后 a 和 b 的值分别是( )。
考点:与 0 异或 0(D1)。
(D1)考点:两个恒等式——(任何位与 0 都清零)和 (任何位异或 0 都不变)。
解析:a = x & 0 每一位都是 ,所以 ;b = x ^ 0 每一位 ,所以 。
排除法:B 把两个恒等式记反;C 以为与 0、异或 0 都清零;D 以为都保持原值。
阅读下面的程序:
01int a = 7, b = 3; 02int c = a ^ b ^ b;
执行后 c 的值是( )。
考点:两次异或还原(D2)。
(D2)考点:——与同一个数异或两次等于没异或。
解析::先算 ,再与 3 异或一次,两次作用抵消,回到 7。运算律: 满足结合律。
排除法:A 选 3 把 a 的初值记成结果;B 选 0 以为异或两次必然清零;C 选 10 把 又加了 6。
已知 a ^ b ^ c = 0,其中 a = 3,b = 5,则 c 的值是( )。
考点:异或方程(D3)。
(D3)考点: 时,等式两边同时异或 可得 ——异或可以移项。
解析:。,,异或得 。
排除法:A 选 1 是 的结果;C 选 8 是 的加法混淆;D 选 15 是 的乘法混淆。
阅读下面的程序:
01int x = 10, y = 6; 02int z = x | (x & y);
执行后 z 的值是( )。
考点:吸收律(D4)。
(D4)考点:——吸收律:内层 x & y 的结果是 x 的位的子集,再与 x 按位或不改变 x。
解析:,,;(2 的位本来就在 10 里)。
排除法:A 选 6 直接取了 y;B 选 14 把内层 & 当成了 |;D 选 2 只算了内层。
阅读下面的程序:
01int a[5] = {2, 3, 2, 4, 3}; 02int ans = 0; 03for (int i = 0; i < 5; i++) 04 ans ^= a[i];
执行后 ans 的值是( )。
考点:异或找唯一数(D5)。
(D5)考点:成对出现的数异或后抵消——、,所以把全体异或起来,剩下的就是只出现一次的那个数。
解析:,其中 、,。
排除法:A 选 14 是把元素全部相加();B 选 0 以为所有数都会抵消;C 选 2 只取了第一个元素。
阅读下面的程序:
01int x = 7; 02x >>= 1; 03x <<= 1;
执行后 x 的值是( )。已知 。
考点:右移丢位不可逆(D6)。
(D6)考点:右移会把移出的低位丢弃,再左移补回来的是 0——低位一旦移出就找不回来,先右移再左移并非无损往返。
解析:,右移 1 位得 (最低位的 1 被丢掉了);再左移 1 位得 ,比原来的 7 少了 1。
排除法:B 选 7 以为右移再左移是无损往返;C 选 3 只算了右移;D 选 8 是 左移 1 位的结果(方向搞反)。
阅读下面的程序,其中 x 的二进制为 0101(十进制 ),k = 3:
01int x = 5; // 二进制 0101 02int k = 3; 03x = x | (1 << k);
执行后 x 的二进制是( )。
考点:设置第 k 位(E1)。
(E1)考点:x | (1 << k) 把第 k 位设置为 1——掩码 1 << k 只在第 k 位为 1,按位或只影响这一位。
解析:,第 3 位(从 0 数起)从 0 变成 1,其他位不变。
排除法:B 选 1001 把 | 当成了"用掩码替换";C 选 0101 认为没变化;D 选 0111 把 k 直接当成了掩码(0101 | 0011)。
阅读下面的程序,其中 x 的二进制为 1111(十进制 ),k = 2:
01int x = 15; // 二进制 1111 02int k = 2; 03x = x & ~(1 << k);
执行后 x 的二进制是( )。
考点:清零第 k 位(E2)。
(E2)考点:x & ~(1 << k) 把第 k 位清零——先构造"第 k 位为 0、其余全 1"的掩码再按位与。
解析:,,,第 2 位被清零,其余位保留。
排除法:A 选 0111 把掩码当成了"保留低 k 位";B 选 1101 清零的是第 1 位;D 选 1111 漏掉了取反。
阅读下面的程序,其中 x 的二进制为 1010(十进制 ),k = 2:
01int x = 10; // 二进制 1010 02int k = 2; 03x = x ^ (1 << k);
执行后 x 的二进制是( )。
考点:翻转第 k 位(E3)。
(E3)考点:x ^ (1 << k) 翻转第 k 位——异或 1 取反、异或 0 不变,掩码 1 << k 恰好只翻第 k 位。
解析:,第 2 位由 0 翻转为 1,其余位不变。
排除法:A 选 1000 是 x & (1 << k) 的结果;B 选 1011 翻转了第 0 位(k 取错);C 选 0110 翻转了第 3 位。
阅读下面的程序,其中 x 的二进制为 1100(十进制 ):
01int x = 12; // 二进制 1100 02int bit = (x >> 2) & 1;
执行后 bit 的值是( )。
考点:测试第 k 位(E4)。
(E4)考点:(x >> k) & 1 取出第 k 位——先把第 k 位移到最低位,再与 1 取最低位。
解析:,12 >> 2 得 ,3 & 1 得 1。第 2 位是 1。
排除法:A 选 0 看错了位(第 2 位其实是 1);C 选 3 只右移没与 1;D 选 4 把 x & (1 << 2) 的掩码值当成了结果。
阅读下面的程序:
01int m = (1 << 4) - 1;
执行后 m 的二进制是( )。
考点:低 k 位全 1 掩码(E5)。
(E5)考点:(1 << k) - 1 是"低 k 位全 1"的掩码—— 的二进制正好是 k 个 1。
解析:,,低 4 位全 1。
排除法:B 选 1000 是 1 << 3 忘了减 1;C 选 0111 是 (移位量算成 3);D 选 11111 多了一位(那是 (1 << 5) - 1)。
阅读下面的程序,其中 x 的二进制为 110101(十进制 ):
01int x = 53; // 二进制 110101 02int k = 3; 03x = x & ((1 << k) - 1);
执行后 x 的值是( )。
考点:提取低 k 位(E6)。
(E6)考点:x & ((1 << k) - 1) 只保留 x 的低 k 位——用低 k 位全 1 的掩码按位与。
解析:,掩码 ,。
排除法:A 选 53 忘了与掩码;B 选 110 把二进制结果当成十进制 110;D 选 6 取的是高三位 110 而不是低三位。
阅读下面的程序:
01int x = 12; 02int y = x & -x;
执行后 y 的值是( )。已知 。
考点:lowbit(E7)。
(E7)考点:x & -x 得到"最低位的 1"(lowbit)——利用补码 让最低位 1 及以下保持不变、以上全部取反。
解析:, 的补码末段为 0100,,正是最低位的 1 的位权。
排除法:A 选 12 把 -x 当成了 x;C 选 8 取的是最高位的 1;D 选 1 以为结果总是 1。
阅读下面的程序:
01int x = 10; 02int y = x & (x - 1);
执行后 y 的值是( )。已知 。
考点:清零最低位 1(E8)。
(E8)考点:x & (x - 1) 把最低位的 1 清零——减一让最低位 1 变 0 且其后全变 1,与原数相与恰好只清掉那一位。
解析:,,,最低位的 1(位权 2)被清掉。
排除法:A 选 9 只算了 x - 1;B 选 2 把结果当成了被清掉的那一位(那是 lowbit 的答案);C 选 0 以为会一次清光所有位。
阅读下面的程序:
01int x = 2; 02if (x & 1 == 0) 03 cout << "A"; 04else 05 cout << "B";
程序的输出是( )。
考点:优先级:& 与 ==(F1)。
(F1)考点:关系运算符 == 的优先级高于位与 &——x & 1 == 0 实际是 x & (1 == 0),这是最常见的位运算陷阱。
解析:1 == 0 为假,即 0;,条件为假,执行 else 分支,输出 B。
排除法:A 是"以为等价于 (x & 1) == 0"的误解(x=2 时该理解得真、会输出 A,与代码实际行为不同);B 编译不会出错;D 不可能输出两个字符。
阅读下面的程序:
01int x = 1 << 2 + 1;
执行后 x 的值是( )。
考点:优先级:移位与加法(F2)。
(F2)考点:移位 << 的优先级低于加法 +——1 << 2 + 1 是 1 << (2 + 1),不是 (1 << 2) + 1。
解析:,。
排除法:B 选 5 是按 (1 << 2) + 1 算的(经典误解);C 选 4 是 1 << 2 后漏了加 1;D 选 9 无运算依据。
阅读下面的程序:
01int a = 6 & 4; 02int b = 6 && 4;
执行后 a 和 b 的值分别是( )。
考点:按位与与逻辑与(F3)。
(F3)考点:& 是按位与,结果是一个数;&& 是逻辑与,结果只有 0 或 1。
解析:,,6 & 4 = 4(按位);6 && 4 中两个数都非 0 即真,逻辑与得真,赋给 int 为 1。
排除法:A 把两个结果对调;B 以为 && 得 0;C 把 & 也当成了逻辑与。
阅读下面的程序:
01int x = 6 ^ 1 | 2;
执行后 x 的值是( )。
考点:优先级:异或与或(F4)。
(F4)考点:优先级从高到低 & → ^ → |——6 ^ 1 | 2 先异或后按位或。
解析:(),()。
排除法:A 选 5 是按"先 | 后 ^"算的(,经典误解);C 选 2 只算了后半段;D 选 3 只算了 1 | 2。
阅读下面的程序:
01int a = 29 % 8; 02int b = 29 & 7;
执行后 a 和 b 的值分别是( )。
考点:取模与掩码(F5)。
(F5)考点:当除数是 时,x % (2^k) 等价于 x & (2^k - 1)——取模就是保留低 位。
解析:;,,。两者相等,因为 ,取模留下的余数恰好是低 3 位。
排除法:A 把 & 7 算成了 3(把 29 看成了 );B 把 % 8 算成了 3(,余数记错);D 把 & 7 当成保留 7 本身。
阅读下面的程序:
01int x = 2; 02x |= 3; 03x <<= 1; 04x ^= 1;
执行后 x 的值是( )。
考点:复合赋值链(F6)。
(F6)考点:|=、<<=、^= 依次生效,每步都在上一步结果上操作。
解析:();;()。
排除法:B 选 6 漏了最后的 ^= 1;C 选 3 漏了 <<= 1;D 选 5 漏了 |= 3(,)。
阅读下面的程序:
01int x = 14; 02if (x & 1) 03 cout << "odd"; 04else 05 cout << "even";
程序的输出是( )。
考点:奇偶判断(G1)。
(G1)考点:x & 1 取出最低位——奇数最低位为 1,偶数最低位为 0,所以 x & 1 等价于"是不是奇数"。
解析:,最低位是 0,14 & 1 = 0,条件为假,输出 even。
排除法:A 把 x & 1 当成了恒为真;C 该写法合法不会编译错误;D 把 x & 1 与 x && 1 混淆(后者才是 1)。
阅读下面的程序:
01int x = 15, cnt = 0; 02while (x) { 03 cnt++; 04 x = x & (x - 1); 05}
执行后 cnt 的值是( )。
考点:统计 1 的个数(G2)。
(G2)考点:x = x & (x - 1) 每执行一次清掉一个最低位的 1,循环次数恰好等于二进制中 1 的个数。
解析: 有 4 个 1:,共 4 轮,cnt 为 4。
排除法:A 选 15 以为循环次数等于 x 的值;B 选 3 少数了一个 1;C 选 2 数了两次清零就停止。
阅读下面的程序:
01bool isPow2(int x) { 02 return x > 0 && !(x & (x - 1)); 03}
调用 isPow2(16) 和 isPow2(12),返回值依次是( )。
考点:判断 2 的幂(G3)。
(G3)考点:x & (x - 1) 清零最低位 1;2 的幂只有一个 1,清零后得 0——但要先排除 。
解析:,,且 ,返回 true;,,返回 false。
排除法:A 把两个结果对调;B 以为 12 也算 2 的幂( 是两个 1);D 以为 16 不是(16 是 )。
阅读下面的程序,其中字符 'A' 的 ASCII 码为 (十六进制 0x41):
01char c = 'A'; 02c = c | 0x20;
执行后 c 变为( )。
考点:大小写转换(G4)。
(G4)考点:ASCII 码大小写字母仅第 5 位不同——大写字母第 5 位为 0、小写为 1,| 0x20 把第 5 位设置为 1 即转小写。
解析:'A' 是 0x41 = 0100 0001,与 0x20 = 0010 0000 按位或得 0110 0001 = 0x61,即 'a'。
排除法:B 认为按位或不改变字符;C 把 | 0x20 当成了"加上 32 个字母序"(0x41 + 0x19 才是 Z);D 把 0x20 当成十进制数字运算。
阅读下面的程序,其中 x = 3(二进制 11):
01int x = 3; // 二进制 11 02int cnt = 0; 03for (int s = x; s; s = (s - 1) & x) 04 cnt++;
执行后 cnt 的值是( )。
考点:子集枚举(G5)。
(G5)考点:for (s = x; s; s = (s - 1) & x) 依次枚举 x 的每一个非空子集(二进制 1 的子集)。
解析:,其非空子集对应二进制 11、10、01。循环依次取 ,共 3 次。
排除法:A 选 4 把空集()也算进去了;C 选 2 漏数了一个子集;D 选 7 把 的全集规模混淆(那是 3 个元素的子集总数减一)。
阅读下面的程序:
01int x = 6; 02while (x) { 03 cout << (x & 1); 04 x >>= 1; 05}
程序的输出是( )。
考点:二进制逆序输出(G6)。
(G6)考点:x & 1 取最低位、x >>= 1 逐位移出——循环会从低位到高位依次输出每一位。
解析:。第 1 轮输出最低位 0, 变 ;第 2 轮输出 1, 变 ;第 3 轮输出 1, 变 0 停止。输出 011。
排除法:A 选 110 是"高位先出"的直觉答案;B 没有依据;D 把数字整体输出(那是 cout << x)。
阅读下面的程序:
01int s = 0; 02for (int i = 1; i <= 8; i++) 03 if (i & 1) s += i; // i 为奇数 04 else s += i >> 1; // i 为偶数
执行后 s 的值是( )。
考点:阅读奇偶分支累加(H1)。
(H1)考点:i & 1 判断奇偶,i >> 1 是整除 2——同一段代码里两个位运算各司其职。
解析:奇数 直接累加得 ;偶数 各右移 1 位(整除 2)得 ,累加得 。总和 。
排除法:A 选 36 是 的全体累加(偶数没右移);B 选 16 只算了奇数分支;C 选 10 只算了偶数分支。
阅读下面的程序,其本意是判断 x 是否为 2 的幂:
01bool f(int x) { 02 return !(x & (x - 1)); 03}
调用 f(0),返回值是( )。
考点:改错零与二的幂(H2)。
(H2)考点:!(x & (x - 1)) 判断 2 的幂必须同时要求 —— 时 x & (x - 1) 得 0,会误判为 2 的幂。
解析:,!0 为 true,所以 f(0) 返回 true。但 0 不是 2 的幂,函数漏了 x > 0 的限制(正确写法见第 42 题)。
排除法:A 是"按数学正确性"回答而非"按代码实际执行"回答;C 循环都不会发生(这是单个表达式);D 代码合法可编译。
阅读下面的程序,其中 x = 12(二进制 1100):
01int x = 12; // 二进制 1100 02int y1 = x & -x; // 保留最低位的 1 03int y2 = x & (x - 1); // 清零最低位的 1
执行后 y1 和 y2 的值分别是( )。
考点:对比 lowbit 与清零(H3)。
(H3)考点:x & -x 保留最低位的 1,x & (x - 1) 清掉最低位的 1——两个公式一"取"一"清",别记混。
解析:。(保留);(清零)。所以 ,。
排除法:B 把两个公式的结果对调(经典混淆);C 把 x & -x 当成了 x、x & (x-1) 当成了 x-1;D 把两个公式都当成了 lowbit。
阅读下面的程序,本意是构造低 k 位全为 1 的掩码:
01int k = 4; 02int m = 1 << k - 1;
执行后 m 的值是( )。
考点:陷阱移位减一(H4)。
(H4)考点:<< 优先级低于 -,1 << k - 1 是 1 << (k - 1);想构造低 k 位全 1 掩码必须写 (1 << k) - 1。
解析: 时 1 << (4 - 1) = 1 << 3 = 8。代码本意是 ,因缺括号算成了 8。
排除法:A 选 15 是"本意"而非"实际执行结果";B 选 16 是 1 << 4 的结果;D 选 7 是 的混淆。
下面的函数本意是:把 x 的第 k 位设置为 1,其他位不变。横线处应填( )。
01int setBit(int x, int k) { 02 return ____; 03}
考点:补全设置第 k 位(H5)。
(H5)考点:设置第 k 位用 | 加掩码 1 << k;& 是测试、^ 是翻转、>> 是移位——四种操作别混用。
解析:x | (1 << k) 只在第 k 位是 1,与 x 按位或恰好把第 k 位设置为 1、其他位不变。
排除法:A 是"测试第 k 位"的写法(结果只有 0 或掩码值);B 是"翻转第 k 位";C 只是右移,与设置无关。
二进制数 11 1011 1001 0111 和 01 0110 1110 1011 进行逻辑与运算的结果是( )。
1 #include <iostream> 2 using namespace std; 3 4 int n; 5 int a[1000]; 6 7 int f(int x) 8 { 9 int ret = 0; 10 for (; x; x &= x - 1) ret++; 11 return ret; 12 } 13 14 int g(int x) 15 { 16 return x & -x; 17 } 18 19 int main() 20 { 21 cin >> n; 22 for (int i = 0; i < n; i++) cin >> a[i]; 23 for (int i = 0; i < n; i++) 24 cout << f(a[i]) + g(a[i]) << ' '; 25 cout << endl; 26 return 0; 27 }
输入的 n 等于 时,程序不会发生下标越界。( )
输入的 a[i] 必须全为正整数,否则程序将陷入死循环。( )
当输入为 5 2 11 9 16 10 时,输出为 3 4 3 17 5。( )
当输入为 1 511998 时,输出为 18。( )
将源代码中 g 函数的定义(- 行)移到 main 函数的后面,程序可以正常编译运行。( )
当输入为 2 -65536 2147483647 时,输出为( )。
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 char base[64]; 6 char table[256]; 7 8 void init() 9 { 10 for (int i = 0; i < 26; i++) base[i] = 'A' + i; 11 for (int i = 0; i < 26; i++) base[26 + i] = 'a' + i; 12 for (int i = 0; i < 10; i++) base[52 + i] = '0' + i; 13 base[62] = '+', base[63] = '/'; 14 15 for (int i = 0; i < 256; i++) table[i] = 0xff; 16 for (int i = 0; i < 64; i++) table[base[i]] = i; 17 table['='] = 0; 18 } 19 20 string decode(string str) 21 { 22 string ret; 23 int i; 24 for (i = 0; i < str.size(); i += 4) { 25 ret += table[str[i]] << 2 | table[str[i + 1]] >> 4; 26 if (str[i + 2] != '=') 27 ret += (table[str[i + 1]] & 0x0f) << 4 | table[str[i + 2]] >> 2; 28 if (str[i + 3] != '=') 29 ret += table[str[i + 2]] << 6 | table[str[i + 3]]; 30 } 31 return ret; 32 } 33 34 int main() 35 { 36 init(); 37 cout << int(table[0]) << endl; 38 39 string str; 40 cin >> str; 41 cout << decode(str) << endl; 42 return 0; 43 }
输出的第二行一定是由小写字母、大写字母、数字和 +、/、= 构成的字符串。( )
可能存在输入不同,但输出的第二行相同的情形。( )
输出的第一行为 -1。( )
设输入字符串长度为 n,decode 函数的时间复杂度为( )。
当输入为 Y3Nx 时,输出的第二行为( )。
当输入为 Y2NmIDIwMjE= 时,输出的第二行为( )。
1 #include <iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 unsigned short x, y; 8 cin >> x >> y; 9 x = (x | x << 2) & 0x33; 10 x = (x | x << 1) & 0x55; 11 y = (y | y << 2) & 0x33; 12 y = (y | y << 1) & 0x55; 13 unsigned short z = x | y << 1; 14 cout << z << endl; 15 return 0; 16 }
删去第 行与第 行的 unsigned,程序行为不变。( )
将第 行与第 行的 short 均改为 char,程序行为不变。( )
程序总是输出一个整数 0。( )
当输入为 2 2 时,输出为 10。( )
当输入为 2 2 时,输出为 59。( )
当输入为 13 8 时,输出为( )。