link

1

自增运算符的位置对返回值的影响。

2*

sizeof不求值表达式,因此第一个 x++ 不会对变量 x 产生副作用。 在几乎所有的现代计算机中,int 包含 4 个字节。

3*

左移运算符 (<<) 的优先级严格低于加法运算符 (+)。

4*

等号/不等号运算符 (=/!=) 的优先级严格低于偏序比较运算符 (</>/<=/>=)。

5

C++ 没有求幂 (**) 运算符,故 a**b 解析为 a * (*b)

6*

编译时,注释 (/*) 替换先于运算符的解析

7

三目运算符是右结合的。

8*

在 C++ 中,三目运算符和赋值运算符具有相同的优先级,且右结合。

9*

在 C 中,三目运算符从不返回左值。

10*

三目运算符不会执行错误分支

11*

在 C 中,三目运算符的优先级严格高于赋值运算符,故此题同 #9。

12

vector 等容器在作为局部变量时默认调用构造函数。

13

C++11 前模板定义不能使用 >>,需添加空格。

14

statement-codes
#include <bits/stdc++.h>
using std::cin;
using std::cout;

typedef std::string foo;

namespace test {
	typedef int foo;
	std::vector <foo> bar;
}

int main() {
	test::bar.resize(1);
	cout << '[' << test::bar.back() << ']' << '\n';
	return 0;
}

命名空间 test 中会使用 test 中的 foo,即 int

15

statement-codes
#include <bits/stdc++.h>
using std::cin;
using std::cout;

typedef std::string foo;

namespace test {
	typedef int foo;
	std::vector <::foo> bar;
}

int main() {
	test::bar.resize(1);
	cout << '[' << test::bar.back() << ']' << '\n';
	return 0;
}

:: 前缀表示无名空间,即外部的 std::string

16

代码同上,使用 C++03 编译

C++11 前,<: 被强制分析为 [ 的代用记号,故上述程序无法成功编译。

17*

十六进制转义序列 \x35 表示字符 '5'

18*

'F' 是合法十六进制数位,这会导致十六进制转义序列超限而无法编译。

19

C++ 中没有负整数常量,-2147483648 表示对 2147483648 取负。而 2147483648 无法用 int 表示。

20

long long后缀” 要么使用 ll,要么使用 LL,大小写不能混用。

21*

0xff = 255

22*

0xff + 2 = 257

23*

eE 结束的十六进制常量在后面紧跟 +- 时,编译器会贪心认为其是浮点数而报错。

24

25

一对孤立的 -- 在一起时总是会被认为是自减运算符。

26*

通过加空格可以避免错误解析;一元运算符具有较高的优先级。

27

贪心的编译器总会将完整的 -- 给左边 (a),故 a --- b 解析为 (a--) - b

28

a---- 被解析为 ( (a--) -- ),而后置自减运算符返回右值,故无法对其再自减。

29

n = (++n) + (n++) + (++n) + (n++);

经典的 UB,不同的编译器会返回各种各样的结果。

30

在 C++11 中,++n 中对 n 的副作用按顺序早于对 n 的值计算,而对 n 的值计算按顺序早于赋值操作。

31*

在 C++11 中,n++ 中对 n 的值计算按顺序早于n 的副作用,也按顺序早于赋值操作,但对 n 的副作用和赋值操作是无顺序的。

32*

函数各参数的求值是*顺序不确定的。

33

UINT_MAX + 1 会导致 int 溢出 (俗称 “爆 int”),因此结果会舍去最高位,变为 0。

34*

有符号整数溢出是 UB。

35

移位数量大于位长为 UB。

36*

左移一个负数是 UB。

37**

右移负数不是 UB,是向上取整 (算术右移)。

38*

C++17 前,??/ 被视作 \ 的 “三标符”;转义序列 \\ 表示单个反斜杠 \

39

“代用记号” (双标符) 的替换在处理注释和字符串之后。

40*

无副作用的无限循环是 UB。

41*

该无限循环有副作用 (返回 n),故不是 UB;Goldbach 猜想在 2642^{64} 范围内成立。

42*

#define 是简单的字符替换,因此该宏会展开为 ((bar()) < (car()) ? (bar()) : (car())),不难得知此时函数 bar() 会被调用两次。而函数即使是 inline,也不会多次调用 bar()

43*

# 运算符会立即将形参转化为字符串常量。

44

PRINT 宏起到一个缓冲作用,使得调用 print 宏时的参数变成了 bar

45*

宏替换会连续应用,直到找不到对应的宏为止。

46*

递归替换抑制规则表明,如果在应用宏替换时遇到递归过程中出现过的宏名,则会保留宏名不再进行替换。

47*

标识符 a 的替换轨迹为 abcdb,在第二次替换到 b 时应用递归替换抑制规则,故 a 的最终结果是 b 而不是 a

48

宏运算符 ## 用于拼接参数。

49

## 可以将 += 拼接成 +=

50*

## 不能用于拼接注释。

51*

## 拼接运算符时,只有它们能组成一个完整的运算符时,该替换才能进行。而 a**b 解析为 a * (*b),在这里 ** 不是一个完整的运算符。

52

特殊宏 __LINE__ 返回当前行号。

53*

“行号” 可以通过 #line 指令更改。

54*

“行号” 始终解析为十进制。

55

continue 的功能是跳转到循环体末尾而不是第二次循环的开头。

56

switch 块内可以定义变量。

57*

switch 的本质是标签跳转 (goto),而标签跳转不允许交叉初始化 (cross initialization),除非进入作用域的所有变量声明时不带初始化器和构造/析构函数。

58*

无限定查找不会找到命名空间 std 中的 sort 函数。

59*

ADL 法则 (阿毒瘤法则) (实参依赖查找) 可以找到实参 std::greater 所在的命名空间 std 中的 sort 函数。

60*

ADL 法则全称实参依赖查找,参数的命名空间不会再通过函数名进行查找。

Results

总题数:60,正确:26,错误:34,进度:100.0%,正确率:43.3% pupil\large\textcolor{green}{{pupil}}