GESP 2025年9月 3级 C++ 真题解析
笔者前面解析了GESP 2025年9月一级和二级的真题,现在来解析一下三级的题目。总的感受是:很多考到了与编译器有关的知识,判断题个个感觉都模棱两可。笔者禁不住想问:这真的是小学生能理解的吗?
首先来看单选题。

这道题考察的是变量的作用域,但同时需要知道编译器的有关知识。C++遵守按需定义的原则,即直到需要某个变量了,才去定义它,这就导致C++中的变量定义不全部在语句块的开始位置,编译器也不会移动变量定义的位置。也就是说,这段代码中第4行定义的sum,编译时不会被移到第3行前面。那么第3行访问的 sum就只能是第1行定义的sum。这是其一。
其二,编译器会进行优化。这段代码中,第4行定义的sum没有任何用处,所以优化时(例如使用 -O2 标志),第4行被直接删除了。
这道了这两点,答案就水落石出了,为B。
第7道和第8道笔者已经在另外一篇文章中解析过了,这里跳过。

这道题考察的也是变量的作用域问题。全局变量是否在整个程序中都有效呢?笔者在4级中专门讲到一点:全局变量的局部化。当对全局变量使用了static关键字后,这个全局变量的作用范围就只在当前的文件中了,就不会在整个文件中都有效了。所以这道题的答案就是C。
(这里要说明的是,GESP 3级大纲中并没有提到变量的作用域,4级中也没有专门针对变量的作用域的条目,它在4级中是作为函数的一部分被包含进来的。所以笔者在4级中才讲到了这部分内容。)

注意:这道题的答案是D,但是这个答案中的数是错误的!
表面看,似乎任何一位变大一点,反转后就越界了(第一位如果变大,这个数本身越界了)。但是可以把个位数变成1,然后其他位就可以变大了啊,比如1963847411,这个数不是比1463847412大吗,它不能反转吗?
实际上,能够反转的最大的正整数是2147483641,即把最大的int型整数2147483647的个位降到1,就能反转了。
不过话说回来,这道题虽然答案错误了,但是题目本身是很有趣的。它不像其他题,如果打字速度够快的话,直接把代码敲到电脑里运行一下结果就出来了。这道题是真正需要人脑思考的,代码敲到电脑里也没有用。

这道题考的仍然是函数的知识。在C中(而不是题目中说的C++11之前),允许函数没有返回值,像这样:
add(x, y) { return a + b; }所以答案为D。选项C,返回值为void类型的函数,也可以有return语句(特别是需要中途返回的情况)。
接下来看判断题。
第 1 题 表达式 sizeof('a') 的结果总是 1 ,因为 'a' 是一个字符。
这道题答案为错误,但是真的很难。理由是,在C中,’a’ 的类型是int,而不是char。这个理由太牵强了,这不是在考C++吗,在C++中,’a’ 不就是char类型吗?这就好比考中文时说“坦克”也有“箱子”的意思,因为坦克的英文是tank,而tank有“箱子”的意思。
第 4 题 在C++中, ++i 是一个左值表达式,而 i++ 是一个右值表达式。
这道题是正确的,但对小学生来说,理解++i和i++的区别已经很困难了,还要理解左值和右值,真的太难了。我敢说,即使很多工作过的人,也不一定知道左值和右值的区别,更不知道++i是一个左值表达式了。
左值表达式是啥意思呢?就是可以放在赋值符号的左边,给它重新赋值。也就说,这样的写法是合法的:
++i = 6;执行这句代码后,i 变成了6,之前的++没有作用。为什么可以这么写呢,因为 ++i 返回了 i 的引用,所以可以直接再赋值。
C++中其实有很多这样的例子。比如数组元素a[i],我们就可以在表达式里使用这个值,也可以给它赋值,a[i] = 6。能给它赋值,就表示它是一个左值。
概言之,返回引用的表达式,就可以作为左值。
第 5 题 对于 enum Color { RED, GREEN, BLUE }; ,RED的类型是 int。
错误。在C++中,枚举是个专门的类型,虽然它的值是整数,但是类型就叫Color。
第 6 题 #define SQUARE(x) x*x 是一个安全的宏定义, SQUARE(2+3) 会正确计算出 25 。
这道题是错误的。我们首先要知道宏的本质,宏就是一个简写,在编译时,宏会被原封不动的替换。看题目中的例子,把2+3替换进去,得到2+3*2+3,结果是11,不是25。所以大家能做出正确判断。但是,如果它不举例子的话,大家能判断出它是错误的吗?
与这个类似的是,a *= b 等价于 a = a*b,安全吗?也不安全。
那么,正确的写法是什么呢?要在x两边加上小括号。#define SQUARE(x) (x)*(x),这样就对了。
第 7 题 在C++中, char 类型的取值范围总是 -128 到 127。
这道题再次考到了编译器的知识。这个说法不正确,因为 char 类型的取值范围在 C++ 标准中没有统一规定,它取决于编译器的实现。不同的编译器对 char 的默认符号性处理不同,有的当成有符号,有的当成无符号。
第 8 题 表达式 a > b ? a : b = 10; 一定是合法的C++代码。
这又是一道很难的题目。根据优先级排序,?: 的优先级高于赋值运算的优先级,所以这句代码应该理解成(a > b ? a : b) = 10,那么它是否一定合法呢?如果a或者b是常量的话,它们就不能再被赋值,因而这句话是错误的。
第 9 题 #include "file.h" 和 #include <file.h> 在编译器查找头文件时的搜索策略是完全相同的。
这又是一道与编译器有关的题目。编译器查找头文件时,针对这两种形式的文件,其搜索顺序是不同的,因而本题错误。最佳实践是,使用 " " 用于项目自有的头文件,使用 < > 用于系统库或第三方库的头文件。
第 10 题 在同一个作用域内, extern 声明的变量可以多次定义。
错误。一个变量可以被多次声明,但不能被多次定义。声明就是告诉编译器这个变量是存在的,说多少次都无所谓。定义是真正创建这个变量,为它准备空间,因而只能有一次。
最后简单地说说编程题第二道。
这道题中我们需要明确知道某一天是礼拜几,然后根据这个信息推算出其他日期是礼拜几。但是题目中说了,“例如,2025 年 9 月 1 日是星期一”,这个“例如”能作为明确的已知信息吗?笔者觉得有待商榷。通常当我们说例如时,都是假设性质的,不会当成明确的已知信息。比如题目中的输入输出样例,这些作为例子用来测试,但不是说真实场景下就是这些数据。笔者认为,已知信息必确明确用“已知”,而不能用“例如”。
本文为学漄乐码堂主撰写。如果您想要学到真正的知识,而不只是应试的技巧,欢迎留言跟我联系。
(写作不易,请大家点赞、关注、收藏、转发!)