2 条题解
-
0
21题为什么官方答案是T?
这道题在 判题机/官方标准答案 和 严谨 C++ 语言学理 上存在经典的争议,但如果是在 GESP 官方考试 / OJ 判分 环境下:
🎯 判题机 / 官方给出的标准答案是:A. 对
💡 为什么官方答案判【对】?(出题人视角)
在初中级编程认证(GESP 四级、二级等)的教学大纲与出题语境中,出题人对“指针传参”的核心考查点通常是:
- 通过指针修改目标数据:对比“普通变量值传递(无法修改外部实参)”,指针传参最大的作用就是可以通过解引用
*p = 100,在函数内部真正修改该指针所关联/引用的外部数据值。 - 形参变量本身合法可写:在 C++ 中,形参
int *p本身是一个普通的局部左值变量,只要没有加const修饰(非int * const p),在函数内部执行p = NULL;或p++;在语法上是完全合法且能正常修改该形参变量的值的。
因此,无论从“通过指针修改它指向的值”,还是“修改这个形参指针变量自身”,在函数内部都是允许修改的,所以官方答案定为 对。
⚠️ 为什么很多同学和资深程序员会觉得应该判【错】?(严格学理视角)
如果从现代 C++ 的严格术语体系来推敲,原题的表述是不严谨的:
- “函数的参数”是值传递(Pass by Value):传入函数的指针形参,只是外部实参指针的一个副本(拷贝)。
- 如果在函数内部写
p = &b;(修改该参数自身的值),外部真实的实参指针完全不受影响。 - 要想真正修改外部指针参数的值,必须使用指针的引用(
int* &p)或二级指针(int** p)。
📌 总结与建议
- 做题拿分(提交 OJ):坚定选 A. 对(与官方题库答案保持一致)。
- 知识掌握:心中要清楚它背后的原理——“能改所指内容,但形参本身是指针副本,无法直接改变外部实参指针的指向”。
- 通过指针修改目标数据:对比“普通变量值传递(无法修改外部实参)”,指针传参最大的作用就是可以通过解引用
-
0
CCF GESP 2024年3月认证 C++ 4级真题 —— NOI 金牌讲师逐题深度剖析与题解
金牌讲师寄语:
GESP 4级是 CCF 编程能力等级认证承前启后的关键级别,重点考查 函数指针与引用传参、二维/多维数组内存模型与寻址、基础排序算法(选择/插入)机理与复杂度分析、C++底层内存对齐与结构体首地址、基本文件流输入、作用域与异常处理 等核心考点。
本题解由 NOI 金牌教练团队倾力编写,不仅给出标准答案,更有深入底层的内存图解、推导逻辑与易错避坑指南,助你建立扎实严谨的计算机底层思维!
快速查对表
单项选择题(15 题,共 30 分)
题号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 官方答案 C D C D A C B C B C 判断题(10 题,共 20 分)
题号 16 17 18 19 20 21 22 23 24 25 官方答案 对 (T) 错 (F) 对 (T) 错 (F) 对 (T) 错 (F) 对 (T)
一、单项选择题(每题 2 分,共 30 分)
第 1 题
【题目内容】
若函数声明为int f(int &x){ x+=3; return x; },则对声明的变量int a=3,下面哪个调用能够改变a的值 ( )。- A.
f(&a); - B.
f(*a); - C.
f(a); - D.
f(a-3);
【答案】C
【考点】 C++ 引用传递(Reference Passing)
【讲师深度解析】- 语法分析:函数的形参为
int &x,表示x是一个整型变量的引用(别名)。在 C++ 中,引用传递在函数调用时语法与传值调用完全相同,直接传入变量名即可:f(a);。进入函数后,形参x与实参a绑定至同一块内存地址,执行x += 3;即直接修改了变量a的值(a变为 6)。 - 选项辨析:
- 选项 A:
&a取出的是a的地址(类型为int*指针),与形参int&类型不匹配,编译错误。 - 选项 B:
a为普通整型变量,对其进行解引用*a属于非法操作,编译报错。 - 选项 C:正确调用,直接传变量名
a,成功通过引用修改a的值。 - 选项 D:
a-3是一个右值(临时表达式),非常量左值引用int&无法绑定到右值,编译报错。
- 选项 A:
第 2 题
【题目内容】
下面C++代码执行后,输出的是( )。int main() { int x[]={2, 0, 2, 4}; char geSP[]="Grade Examination of SP"; cout << geSP[sizeof(x)] << endl; cout << endl; return 0; }- A.
G - B.
e - C.
n - D.
P
【答案】C
【考点】sizeof运算符计算数组字节大小、字符串下标访问
【讲师深度解析】sizeof求解:数组x定义为int x[] = {2, 0, 2, 4};,包含 4 个int元素。在现代标准系统及竞赛标准环境下,sizeof(int) == 4字节,因此sizeof(x) = 4 * 4 = 16字节。- 下标检索:题目输出
geSP[16]。我们对字符串"Grade Examination of SP"从 0 开始逐字符索引:0: 'G',1: 'r',2: 'a',3: 'd',4: 'e',5: ' '6: 'E',7: 'x',8: 'a',9: 'm',10: 'i',11: 'n',12: 'a',13: 't',14: 'i',15: 'o'16: 'n'
因此geSP[16]对应的字符是'n'。选 C。
第 3 题
【题目内容】
下面C++代码执行后输出是( )。int foo(float *f) { return int(*f*2); } int main() { float fnum[10]={1.1}; fnum[1]=foo(fnum); cout << fnum[0]+fnum[1] << endl; cout << endl; return 0; }- A.
1 - B.
1.1 - C.
3 - D.
3.1
【答案】D
【考点】 数组名退化为指针、指针解引用、强制类型转换与浮点算术运算
【讲师深度解析】- 初始化:
float fnum[10]={1.1};将fnum[0]初始化为1.1,其余元素自动清零。 - 函数调用:
foo(fnum)传入数组首地址,形参f指向fnum[0]。*f取出fnum[0]的值1.1。*f * 2计算结果为2.2。int(*f * 2)强制向下截断转换为整数,结果为2。
- 赋值与累加:
fnum[1] = 2。- 最终输出
fnum[0] + fnum[1] = 1.1 + 2 = 3.1。
故输出为3.1,选 D。
- 最终输出
第 4 题
【题目内容】
对二维数组int arr[3][16];,则arr[1]占用内存的大小为( )字节。- A.
4 - B.
16 - C.
48 - D.
64
【答案】D
【考点】 二维数组内部组成及行数组的内存大小计算
【讲师深度解析】- 二维数组结构:在 C++ 中,二维数组
arr[3][16]本质上是由 3 个一维数组(行)组成的数组。 arr[1]含义:arr[1]代表第 1 行(第二行)这个一维子数组,该子数组包含 16 个int元素。- 字节大小:每个
int占用 4 字节,故sizeof(arr[1]) = 16 * sizeof(int) = 16 * 4 = 64字节。选 D。
第 5 题
【题目内容】
对二维数组int arr[3][16];,若arr的地址是0x28cbc0,则arr[1]的值是( )。- A.
0x28cbc4 - B.
0x28cbd0 - C.
0x28cc00 - D. 不确定
【答案】C
【考点】 二维数组内存连续性与十六进制指针偏移运算
【讲师深度解析】- 行首地址偏移量:二维数组在物理内存中按行优先连续存放。
arr[1]是第 1 行的首地址,相对于第 0 行首地址arr[0](即arr的基地址)偏移了整整一行的元素容量。- 第 0 行包含 16 个
int元素,总字节大小为 字节。
- 第 0 行包含 16 个
- 十六进制进制转换与相加:
- 转换为十六进制是
0x40(因为 )。 - 基地址为
0x28cbc0。 - 计算偏移后地址:
0x28cbc0 + 0x40 = 0x28cc00。
(低位十六进制计算:0xc0 + 0x40 = 0x100,产生进位,0x28cb + 0x1 = 0x28cc,末尾为00)。
因此arr[1]的值是0x28cc00。选 C。
- 转换为十六进制是
第 6 题
【题目内容】
下面C++代码执行后输出是( )。int main() { char *p="I love GESP!"; cout << p+5 << endl; cout << endl; return 0; }- A.
e - B.
I lov - C.
e GESP! - D.
GESP!
【答案】C
【考点】 字符指针算术偏移与cout输出字符串机制
【讲师深度解析】- 字符串指针偏移:指针
p指向字符串字面量"I love GESP!"的起始字符(下标 0 处的'I')。- 下标 0:
'I' - 下标 1:
' ' - 下标 2:
'l' - 下标 3:
'o' - 下标 4:
'v' - 下标 5:
'e'
- 下标 0:
- 输出流特性:
p + 5得到指向下标 5(即字符'e')的char*指针。当std::cout接收到一个char*指针时,会将其解释为 C 风格字符串,从该地址开始连续打印字符,直到遇到字符串终止符'\0'为止。
因此输出为"e GESP!"。选 C。
第 7 题
【题目内容】
下面C++代码执行以后输出的是( )。int rc=5; int main() { int rc; cout << ++rc << endl; cout << endl; return 0; }- A.
0 - B.
1 - C.
6 - D. 不确定
【答案】D
【考点】 局部变量作用域遮蔽(Shadowing)与未初始化局部变量的不确定值
【讲师深度解析】- 作用域遮蔽:在
main函数内定义了局部变量int rc;。根据 C++ 的变量遮蔽规则,局部变量会隐藏同名的全局变量int rc = 5;。 - 未定义行为(Undefined Behavior):函数内部定义的局部非静态整型变量
int rc;分配在栈区上,编译器不会自动赋予初值,其内存中残留的是随机的“垃圾值”。 - 对一个未初始化的变量执行
++rc并读取输出,输出结果是不确定的。选 D。
第 8 题
【题目内容】
下面C++函数中采用的算法是( )。int fib(int n) { int i, f[n]={0, 1}; for(int i=2; i<=n; i++) f[i]=f[i-1]+f[i-2]; return f[n]; }- A. 递推
- B. 递归
- C. 迭代
- D. 循环
【答案】A
【考点】 经典基础算法思想辨析(递推 vs 递归)
【讲师深度解析】- 递推(Recurrence):已知初始边界状态(
f[0] = 0, f[1] = 1),根据递推转移方程 ,自底向上、步步推导出最终目标 ,这是标准的递推算法。 - 选项对比:递归(Recursion)是自顶向下调用函数自身;循环和迭代属于程序设计的控制流结构,而“递推”是严谨的算法设计范式。在全国各类认证和 NOIP/CSP 题库中,该题考察的标准算法思想为递推。选 A。
第 9 题
【题目内容】
插入排序在最好情况下的时间复杂度是( )。- A.
- B.
- C.
- D.
【答案】C
【考点】 插入排序(Insertion Sort)的渐近时间复杂度分析
【讲师深度解析】- 最好情况:当输入数据本身已经处于**完全升序(有序)**状态时。
- 比较次数:算法从第 2 个元素遍历到第 个元素,每次将当前待插入元素与前一个元素比较一次,发现当前元素已经大于前驱元素,无需任何元素后移,内层
while循环立即终止。 - 总操作次数:整个排序过程只需进行 次比较和 0 次移动,因此最好时间复杂度为 。选 C。
第 10 题
【题目内容】
在如下的C++代码执行后,设第11和12行的输出地址值分别为 X 和 Y ,则下面正确的是( )。struct pass{ int no; char name[20]; int level; }; int main() { struct pass XiaoYang; cout << "&XiaoYang=" << &XiaoYang << endl; //第11行 cout << "&(XiaoYang.no)=" << &(XiaoYang.no) << endl; //第12行 cout << endl; return 0; }- A.
X>Y - B.
X==Y - C.
X<Y - D. 不确定
【答案】B
【考点】 结构体内存布局与第一个成员首地址规则
【讲师深度解析】- C++ 标准规定:根据 C++ 内存布局与内存对齐规范,结构体对象的首地址必定与它的第一个非静态成员的首地址完全重合(偏移量 offset 为 0)。
- 代码分析:
XiaoYang的第一个成员正是int no;,因此结构体变量本身的首地址&XiaoYang与其首个成员的地址&(XiaoYang.no)在数值上完全相等。即X == Y。选 B。
第 11 题
【题目内容】
如果文件1.txt中的内容如下,则执行下面C++代码时,注释了####那行代码所输出的x的值为( )。50 2024 3.16 I love GESP!int main() { ifstream fin; string line; int x; fin.open("1.txt",ios::in); for (int i=0; i< 2; i++){ fin >> line; cout << line << endl; } fin>>x; cout << x << endl; //#### cout << endl; return 0; }- A.
5 - B.
2024 - C.
3 - D.
0
【答案】C
【考点】 文件输入流(ifstream)、空白符分词与流读取类型匹配规则
【讲师深度解析】- 流输入运算符
>>的机制:以空格、换行、制表符等空白字符作为分隔符。 - 逐步推导读取过程:
- 第 1 次循环
fin >> line;:跳过前导空白,读取第 1 个字符串 token,line = "50"。 - 第 2 次循环
fin >> line;:读取第 2 个字符串 token,line = "2024"。 - 循环结束后执行
fin >> x;(其中x为int类型):流读取下一个 token,文件下一个内容是"3.16"。
- 第 1 次循环
- 整型读取浮点数据:流按整型解析时,读取到数字
'3',当遇到下一个字符小数点'.'时,由于.不是合法的十进制整数构成字符,流读取在此停止,将已解析出的整数3赋值给x,小数点及后续字符留在输入流缓冲区中。
因此x的值为3。选 C。
第 12 题
【题目内容】
执行下列C++代码时输出中的第2行是( )。int main() { char *s[]={(char*)"2024",(char*)"3.16",(char*)"GESP"}; for (int i=0; i< 2; i++){ cout << *s+i << endl; } cout << endl; return 0; }- A.
2024 - B.
3.16 - C.
024 - D.
3
【答案】C
【考点】 指针数组的指针运算与运算符优先级陷阱
【讲师深度解析】- 关键陷阱辨析:代码输出的是
*s + i,注意不是*(s + i)! - 运算优先级与语义:
s是指针数组,数组名s退化为指向第一个元素s[0]的二级指针(char**)。- 解引用运算符
*的优先级高于加法+,因此*s + i等价于(*s) + i。 *s取出的是s[0],即指向字符串"2024"的字符指针(char*)。
- 逐行输出分析:
- 当
i = 0时:输出*s + 0,指向"2024"的起始位置,第 1 行输出2024。 - 当
i = 1时:输出*s + 1,将指向"2024"的指针向后偏移 1 个字节,指向字符'0',第 2 行输出024。
故输出中的第 2 行是024。选 C。
- 当
第 13 题
【题目内容】
C++语言中下面哪个关键字能够限定对象的作用域( )。- A.
extern - B.
static - C.
inline - D.
public
【答案】B
【考点】 C++ 作用域、生命周期修饰符(static)
【讲师深度解析】static的作用:- 修饰全局变量或函数时,将其作用域(链接属性)限制在当前编译单元(当前源文件内),防止被其他文件通过
extern访问; - 修饰局部变量时,将其生命周期延长至整个程序运行期,但作用域仍局限在局部函数块内。
- 修饰全局变量或函数时,将其作用域(链接属性)限制在当前编译单元(当前源文件内),防止被其他文件通过
- 其他选项辨析:
extern:用于扩大变量或函数的引用范围(外部链接),而非限定缩小;inline:用于建议编译器内联展开函数以减少函数调用开销;public:类/结构体的访问控制权限说明符,控制成员的访问权限,而非限定对象本身的作用域。
故选 B。
第 14 题
【题目内容】
小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是( )。- A. 小程序
- B. 计时器
- C. 操作系统
- D. 神话人物
【答案】C
【考点】 计算机基础常识(系统软件分类与国产操作系统)
【讲师深度解析】
华为鸿蒙(HarmonyOS / OpenHarmony)是华为技术有限公司研发的面向万物互联时代的分布式操作系统(Operating System, OS),涵盖手机、智能手表、平板及物联网设备。选 C。
第 15 题
【题目内容】
中国计算机学会(CCF)在2024年1月27日的颁奖典礼上颁布了王选奖,王选先生的重大贡献是( )。- A. 制造自动驾驶汽车
- B. 创立培训学校
- C. 发明汉字激光照排系统
- D. 成立方正公司
【答案】C
【考点】 计算机文化与名人名家(“汉字激光照排系统之父”王选院士)
【讲师深度解析】
王选院士(1937—2006)被誉为“汉字激光照排系统之父”,他主持研制了汉字激光照排系统,使中国传统出版印刷行业“告别铅与火,迎来光与电”,为中华文明的信息化跨越作出了不可磨灭的巨大历史贡献。CCF 设立“CCF 王选奖”正是为了表彰在计算机领域取得重大原始创新成果与突出奉献的学者。选 C。
二、判断题(每题 2 分,共 20 分)
第 16 题
【题目内容】
对int a[]={2,0,2,4,3,1,6},执行第一趟选择排序处理后a中数据变为{0,2,2,4,3,1,6}。( )【答案】对(正确)
【考点】 选择排序(Selection Sort)单趟模拟
【讲师深度解析】- 选择排序第一趟的处理过程:在待排序区间
a[0...6]中寻找全局最小值。 - 数组元素为
[2, 0, 2, 4, 3, 1, 6],遍历比较可得最小值为0,其所在下标为1。 - 将该最小值与区间的首个元素
a[0](值为 2)进行交换。交换后下标 0 变为0,下标 1 变为2,其余元素位置保持不动。 - 处理后的数组为
{0, 2, 2, 4, 3, 1, 6}。描述完全正确。
第 17 题
【题目内容】
如果待排序数据不能都装进内存,需要使用外排序算法。( )【答案】对(正确)
【考点】 内部排序与外部排序(External Sorting)的本质区别
【讲师深度解析】- 内排序:待排序记录全部存放在计算机内存中进行的排序。
- 外排序:由于数据量极其庞大,整个序列无法一次性完整载入内存储器,在排序过程中必须借助于外部存储器(如磁盘、固态硬盘、磁带等)进行分块读取、分段归并(如 路平衡归并排序)的算法。说法完全正确。
第 18 题
【题目内容】
定义变量int a=5, 则cout << &++a会输出6。( )【答案】错(错误)
【考点】 取地址运算符&、前缀自增运算符与输出流行为
【讲师深度解析】- 在 C++ 中,
++a是前缀自增,返回的是变量a自身的左值引用(值变为 6)。 - 对左值使用取地址运算符
&,得到的是变量a在内存中的物理地址(指针类型int*),例如十六进制形式的0x7ffd5e2a3b14。 std::cout << &++a输出的是该内存地址,而不是变量存储的数值6。因此说法错误。
第 19 题
【题目内容】
两个函数之间可以使用全局变量来传递数据。 ( )【答案】对(正确)
【考点】 全局变量的作用域与跨函数数据共享
【讲师深度解析】
全局变量定义在所有函数体外部,在整个程序的运行期内都持续存在,且对当前文件中该定义之后的所有函数都是可见的。一个函数修改全局变量的值,另一个函数直接读取该全局变量,便能达到数据传递与共享的目的。尽管在工程开发中不鼓励滥用全局变量,但语法上完全支持。说法正确。
第 20 题
【题目内容】
定义数组int a[2024][3][16]={2,0,2,4,3,1,6},则cout << a[2023][2][15]的结果不确定。( )【答案】错(错误)
【考点】 多维数组的部分列表初始化规则(补零机制)
【讲师深度解析】- C++ 初始化标准:当对一个具有固定维度的数组提供聚合初始化列表
{...}时,列表中的元素按行优先线性顺序依次赋值给前面的元素。 - 剩余元素清零:所有未在初始化列表中显式指定的剩余元素,编译器必须保证其值被值初始化为对应类型的零值(对于
int即为0)。 a[2023][2][15]是该三维数组在内存中的最后一个元素,属于未显式初始化的范围,因此它的值被严格且确定地初始化为0,绝非不确定的垃圾值。故“结果不确定”说法错误。
第 21 题
【题目内容】
在C++语言中,函数的参数为指针时,可以在函数内部修改该参数的值。( )【答案】对(正确)
差异与学术备注:
- 官方/常规题库认定标准(对):在等级考试教学语境中,常规考查“通过传入指针实现在函数内部修改外部数据或该参数对应目标的值”(例如通过解引用
*ptr = new_val修改其所指内容,或者在函数内改变指针变量本身的地址值)。因此本题官方答案判定为 对。 - 严谨语言标准补充说明:如果从非常严谨的 C++ 语义概念辨析,“指针形参本身也是按值传递的一份地址拷贝”,若在函数内部仅执行
ptr = new_addr,改变的只是形参副本,外部实参指针本身的指向并不会改变(改变实参指针本身需使用指针引用Type*&或二级指针Type**)。但由于指针本身作为形参变量在函数局部内是可以被任意赋值修改的,且可通过解引用修改所指数据,在 GESP 等级考规范下标准答案为 对。
第 22 题
【题目内容】
在C++语言中try子句里抛出的结构体等类型的异常无法被catch捕获。( )【答案】错(错误)
【考点】 C++ 异常处理机制(try-catch-throw)
【讲师深度解析】
C++ 具有极强的类型系统,throw语句可以抛出任意类型的异常对象,包括基本内置类型(如int,const char*)、STL 异常类以及自定义的struct和class对象。catch语句只要指定了对应的类型(如catch (const MyStruct& e)或catch (...)通配捕获),就可以完美捕获处理结构体异常。因此“无法被捕获”说法错误。
第 23 题
【题目内容】
C++语言中cout << 9^2 << endl;会输出81。( )【答案】错(错误)
【考点】 位运算符异或^与运算符优先级
【讲师深度解析】- 运算符含义:在 C++ 语言中,符号
^是按位异或(Bitwise XOR)运算符,绝对不是数学中的乘方(幂)运算符。求幂需要使用<cmath>中的pow()函数。 - 计算过程:
- 9 的二进制表示为:
0000 1001 - 2 的二进制表示为:
0000 0010 - 异或规则(相同为 0,相异为 1):
9 ^ 2 = 0000 1011(即十进制的11)。 - 另外,由于流输出运算符
<<的优先级高于异或^,cout << 9^2实际上会被优先解析为(cout << 9) ^ 2,导致语法或逻辑错误。无论如何都不可能输出81。说法错误。
- 9 的二进制表示为:
第 24 题
【题目内容】
小杨今年春节回奶奶家了,奶奶家的数字电视要设置ip地址并接入到WIFI盒子才能收看节目,那这个WIFI盒子具有路由器的功能。( )【答案】对(正确)
【考点】 计算机网络与网络互联设备常识
【讲师深度解析】
家庭常用的所谓“WIFI盒子”(无线路由器/家庭智能网关),集成了无线接入点(AP)、路由器(具备 DHCP 动态分配私有 IP 地址、NAT 网络地址转换、路由数据包转发)等多项核心功能。电视需要设置 IP 地址并连接该盒子才能访问网络收看节目,说明该设备正在执行路由与寻址功能,具备路由器的功能。说法正确。
第 25 题
【题目内容】
任何一个for循环都可以转化为等价的while循环( )。【答案】对(正确)
【考点】 程序基本控制流结构的等价转换
【讲师深度解析】- 语法转换原理:任何标准的
for循环结构:
均可以无缝等价改写为如下的for (初始化表达式; 条件表达式; 迭代表达式) { 循环体; }while循环结构:{ 初始化表达式; while (条件表达式) { 循环体; 迭代表达式; } } - 特殊情况考虑:即使循环体内包含
continue,在改写为while时只需将迭代表达式放置在continue跳转之前的各分支即可,在图灵完备性和控制流图结构上,二者完全等价。说法正确。
- A.
- 1
信息
- ID
- 4759
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 0
- 上传者