【信奥教练心得】“懂了“是最危险的信号——如何让学生学会自我验证
【信奥教练心得】"懂了"是最危险的信号——如何让学生学会自我验证
真正的"懂了",不是他说出来的,是他自己验证出来的。
📌 本文是「信奥教练手记」专栏的第六篇。

前面五篇,我们聊了教材设计、信息学的乐趣、解题教学闭环、教学节奏,以及让学生把思考的路走完。
方法有了,节奏有了,心态也有了。
但最近我越来越被一个问题困扰:学生说"懂了"的时候,我怎么知道他真的懂了?
这个问题看起来简单,实际上非常棘手。因为"懂了"这个信号,是我教学中收到的最不可靠的反馈。
目录
- 📖 引言:两个"懂了"
- 🧠 第一部分:他不是在骗你——"懂了"是个错觉
- 🔍 第二部分:当"会写"只是一个错觉——如何练习
- 🎯 第三部分:从"假的懂了"到定位真误解——如何学习新知识并确保消化
- 🛠️ 第四部分:教他练习,而不是教他答案
- ⚡ 第五部分:“一题当三题”——证明错误法
- 💻 第六部分:编程给了一件武器——直接验证
- 🌉 结语:两个"懂了"之间
📖 引言:两个"懂了"
先讲两个学生的故事。
第一个学生,从其他机构转过来。前老师的教学方式似乎是"跟着我敲"——老师在上面写,学生在下面抄。他敲了一段时间,看起来"都会了",能写出完整的程序。但我逐步抽查后发现:他不理解变量的本质是内存,会把 = 和 == 搞混,甚至以为"循环"只是这个语法结构的名字,不知道它的真实执行行为是什么。
他不是在骗我。他是真的以为自己会了。😶
第二个学生,我带他练习 GESP 一级选择题。第一次做,几乎每题都错。他产生了很大的恐惧,不敢做题。我带他一步步拆解——逐句读代码、定位误解、用草稿模拟数据、学习"证明错误法"。到最后新卷子出来,正确率百分百。
他看着屏幕上的成绩,对我说:“原来如此。” ✨
同样两个字——“懂了”。第一个学生说的时候,他其实不懂。第二个学生说"原来如此"的时候,他真的懂了。
这两个"懂了"之间,隔着整套教学操作。这就是今天要聊的事。 📌
🧠 第一部分:他不是在骗你——"懂了"是个错觉
很长一段时间,我都以为学生说"懂了"但其实没懂,是在敷衍我。后来我发现不是。
认知科学里有一个被研究了几十年的概念,叫**“能力错觉”(Illusion of Competence)**。它指的是:学习者会在信息被流畅地加工时,产生一种"我掌握了"的真实感觉——但这个感觉是假的。
原因在于人脑有两套完全不同的记忆机制:
- 识别(Recognition):看到信息时认出"我见过这个"。快、自动、省力。听讲、看代码、跟着敲,都在训练这个。
- 提取(Retrieval):不看任何材料,从记忆中重建信息。慢、费力、容易出错。考试、“自己讲一遍”、“为什么这样做”,要求的都是这个。
学生听我讲完一个知识点,大脑流畅地处理了这些信息,产生了"我理解了"的真实信号。但那个信号反映的是"识别",不是"提取"。 他听懂了我说的话,不代表他能自己重现这个推理。
更关键的是——他自己分不清这两者的区别。
尤其是小学阶段的学生。研究表明,有效的理解监控能力(元认知)大约在 9-10 岁才开始发展,而小学生在认知要求较高的任务上会系统性高估自己的理解程度。也就是说,小学生说"我懂了"的时候,他的大脑还没发育出足够的能力来判断自己到底懂没懂。
所以,面对小学生,"不懂装懂"其实是双重原因叠加:
| 层面 | 原因 | 表现 |
|---|---|---|
| 心理层面 | 怕被认为自己学不会 | 明明没懂,但说"懂了" |
| 认知层面 | 元认知监控系统还没发育好 | 以为自己懂了,其实没懂 |
他不是态度有问题,是发育阶段的问题。
这意味着:我不能指望学生自己告诉我他懂没懂。我得替他当那个"验证器",直到他自己的元认知能力发育跟上来。 🔧
🔍 第二部分:当"会写"只是一个错觉——如何练习
第一个学生刚转过来的时候,我让他写了一段简单的代码。他写出来了,格式工整,运行正确。
如果只看到这一步,我会觉得"这孩子基础不错"。
但我开始抽查。我指着代码里的一行问他:“这个 int a = 3,计算机内部发生了什么?”
他愣住了。
他不知道 a 是内存里的一块空间,不知道 3 被存进了那块空间,不知道变量名 a 是那块空间的标签。对他来说,int a = 3 就是一句"咒语"——前老师似乎告诉他这么写,他就这么写,跑通了就行。
我又问:“= 和 == 有什么区别?”
他说:“一个是赋值,一个是判断。”
我说:“那你给我讲讲,赋值的时候计算机做了什么?判断的时候又做了什么?”
他答不上来。
我再问循环。他背得出 for 循环的格式,但当我问他"循环体里的代码在第几次执行?"他回答不上来。他以为"循环"只是这个语法结构的名字,就像人的名字一样——叫"张三"不说明任何关于这个人的信息。
这个学生的问题不是"没学过",而是"学过但没有理解"。 🔍 他的学习方式是"跟着敲",从头到尾都在识别模式下运转——看到代码,认出它,抄下来。从来没有进入过提取模式——停下来想"这行代码到底在做什么"。
而且,这种错觉已经潜伏了很久。如果不是我抽查,它会一直潜伏下去,直到某一天他遇到一道无法靠"抄"来解决的题,然后彻底崩塌。

故事插画一:他敲过很多代码,却从未理解过一行——"跟着敲"养成了识别,却没有培养提取
那节课我没有教新东西
发现这些问题后,我没有立刻开始补知识点。那节课,我做了三件事。
第一件事:用他听得懂的例子,重建概念。
我跟他聊"抽屉"。
“变量就像一个贴了标签的抽屉。int a = 3 就是:找一个抽屉,贴上标签 a,往里面放一个 3。以后你说 a,就是在说’打开那个贴了 a 标签的抽屉,看看里面是什么’。抽屉在哪个柜子里?那个柜子就是内存。”

图1:变量就像贴了标签的抽屉,内存就是那整排柜子
他的眼睛动了一下。不是那种"我在听"的机械反应,而是真的在想。
我又用"放进去"和"看一眼"来区分 = 和 ==:
“= 是一个动作:把东西放进去。a = 3 就是把 3 放进 a 这个抽屉。== 是一个提问:看一眼,里面是不是 3?你不会把’放进去’和’看一眼’搞混,对吧?”
然后讲循环。我说:“做5遍广播体操,你不是一次性做5遍,对吧?你是做完一遍,数一下,没到5就再做一遍,到了就停。for 循环的三个部分就是:从第几遍开始、做到第几遍、每做完一遍之后干什么。”
这些例子不是随便找的。它们必须是他这个年龄会遇到的场景——抽屉、放东西、做广播体操。如果你用"内存地址映射"来讲,他只会更懵。
第二件事:画流程图和思维导图,建立知识图谱。
光听例子还不够。例子是碎片,他需要看到碎片之间的关系。
我在纸上画了一张图:从"数据类型"出发,连到"变量"(变量必须有类型),从"变量"连到"赋值"(=,往抽屉里放东西),再连到"比较"(==,看一眼抽屉里是什么),从"比较"连到"判断"(if,根据看到的结果做选择),从"判断"连到"循环"(for/while,重复做选择和执行)。
画完之后,我让他自己对着图讲一遍:“从数据类型开始,你能把这些概念串起来吗?”
他讲得磕磕绊绊,但方向是对的。这张图给了他一个"地图"——以前他脑子里是一堆散落的点,现在至少有了路。
第三件事:建立信息交流通道,不追求他马上学会。
那节课的最后,我跟他说了一句话:“今天不要求你都记住。你回去消化几天,下次来的时候,哪里还想不通,你就告诉我。”
这句话不是客套。我是认真的。
这个学生之前的学习方式是"被动接收",突然让他"主动理解",他的大脑需要时间来重新布线。如果我逼他这节课就全搞懂,他会回到老路——假装懂了,然后继续在识别模式下混下去。
我需要他做的第一件事,不是"学会",而是"愿意告诉我他哪里没懂"。
这就是建立信息交流通道的意思:我要让他知道,在这个教室里,"没懂"不是丢脸的事,是正常的信息。他只要愿意说出来,我就能帮他。但他如果不说,我就是在和一座沉默的墙对话。
那节课,我不追求他马上学会。我追求的是:他下次来的时候,敢对我说"老师,那个抽屉的例子,我还是有点没想通"。
这比他这节课"记住" = 和 == 的区别重要得多。
🎯 第三部分:从"假的懂了"到定位真误解——如何学习新知识并确保消化
第二个学生,是完全不同的情况。
他不是基础薄弱,而是新知识没消化。具体来说,是循环的执行流程没搞对。但这个错误,他自己完全不知道。

故事插画二:从"几乎全错"到"百分百正确"——他在自我验证中走完了整条路
我带他练习 GESP 一级选择题。第一次做,几乎每一题都错。他开始恐惧,不敢做题。
我让他做一道循环代码的阅读题。我的要求很简单:逐句告诉我,这行代码做了什么。
他的第一反应是:“老师,我可以在选项里排除——”
我打断他:“我们现在不是在考试。我们是在训练你读懂代码的能力。排除法是考试技巧,不是理解能力。”
这里暴露了一个很常见的问题:学生把"练习"当成了"考试"。 在考试里,排除法是合理的策略——你不需要真懂,只需要选出正确答案。但在练习里,用排除法等于用识别(看选项认脸)回避提取(真正读懂代码)。这在训练中是完全无效的。
他开始认真看代码了。但回答得踉踉跄跄,模棱两可。
我追问:“for(int i=0; i<n; i++) 这个循环,执行顺序是什么?”
他说:“先执行 int i=0,再执行 i<n 判断,再执行 i++。”
到这里,我已经精确地定位了他的误解。 🎯
他认为循环的执行顺序是:初始化 → 条件判断 → i++ → 循环体。
但实际的顺序是:初始化 → 条件判断 → 循环体 → i++ → 条件判断 → 循环体 → i++ → ……
也就是说,他认为 i++ 在循环体之前执行,但实际上 i++ 在循环体之后执行。

图2:for 循环的正确执行顺序(上)与学生的常见误解(下)——以为先执行 i++,再执行循环体
这个错误在他的大脑里是自洽的——他用这个错误的模型"解释"了所有循环代码,从来没有报错。因为他的元认知监控系统没有报警:他不觉得自己理解错了,因为他从来没有被要求验证过自己的理解。
“会执行” ≠ “理解了”
我告诉他正确的执行顺序后,他点了点头:“哦,这样啊。”
这个"哦"是另一个危险信号。他知道正确的步骤了,但他不理解这段代码在做什么。
我问他:“那这段代码整体在做什么?”
他答不上来。
这其实是两种不同层次的知识:
- 程序性知识:知道每一步怎么走(初始化→判断→循环体→更新)
- 概念性知识:知道整体在做什么(比如"把1到n的数加起来")
他有了程序性知识,但缺概念性知识。能复述步骤,但不理解意图。
草稿模拟:从"按指令做"到"自己理解价值"
我鼓励他在草稿纸上假设一个数据,代入追踪。
“你假设 n=3,然后在纸上一步一步走,看最后输出什么。”
他照做了。但刚开始的时候,他只是按照我的指令在做——我让他代入,他就代入;我让他记录,他就记录。他还没有真正理解草稿的价值,他只是在配合我。
这很正常。脚手架刚搭上去的时候,学生不会立刻理解它为什么有用。他需要先通过"照做"拿到结果,然后回头才会意识到"哦,原来这样画一下就清楚了"。
他代入完数据,看完了代码,然后我让他去选四个选项里的正确答案。
他很快给出了答案。但答案是错的。
这就是放手的价值。 如果我一直扶着他,他永远不会发现自己的理解有漏洞。我让他独立做,错误自己暴露了出来——5题错3道,还有1题是蒙对的。
但重要的不是我发现了他的错误,而是他自己看到了自己的错误。💡
🛠️ 第四部分:教他练习,而不是教他答案
5题错3道之后,我没有批评他。因为错答案只是表象,不会练习才是根源。
我开始教他怎么练习选择题。
第一步:看清每一个选项里的名词。
“选项里如果出现一个你不认识的词,先停下来,确认它是什么意思。不要跳过去。”
很多学生做选择题的错误,不是逻辑推理错了,而是根本没看懂选项在说什么。一个名词不认识,整句话的理解就歪了,但学生不会停下来查——他会"猜"一个意思,然后基于错误的理解去选。
第二步:把"选对的"变成"论证每个选项填进去之后会发生什么"。 📝
这是我最核心的方法。我拿出了一道真实的考题——2026年6月GESP一级的第13题(题目来源:CCF GESP官方试卷)。
这道题要找"四叶玫瑰数"——一个四位数,如果它各位数字的四次方之和等于它本身,就算一个。比如 1634 = 1×1×1×1 + 6×6×6×6 + 3×3×3×3 + 4×4×4×4。代码已经写好了,但提取十位的那一行被挖空了,让你填:
int count = 0;
for (int n = 1000; n <= 9999; n++) {
int a = n / 1000;
int b = (n / 100) % 10;
___________________________
}
// L1
int d = n % 10;
if (a * a * a * a + b * b * b * b + c * c * c * c + d * d * d * d == n) { // 特定条件
count++;
}
四个选项分别是:
- A.
int c = (n / 10) / 10; - B.
int c = (n / 10) % 10; - C.
int c = (n % 10) / 10; - D.
int c = (n % 10) % 10;
我没有让他"选答案"。我让他做的是:把每一个选项填进去,告诉我运行结果是什么。
他开始逐个分析。
选项 A:int c = (n / 10) / 10;。假设 n=1234,1234 / 10 = 123,123 / 10 = 12。提取出来是 12。这不是十位数,是"十位和百位拼在一起"。✗
选项 B:int c = (n / 10) % 10;。1234 / 10 = 123,123 % 10 = 3。提取出来是 3。正确十位是 3。✓
到这里他停住了:“B 是对的。”
我说:“别急,继续。”
选项 C:int c = (n % 10) / 10;。1234 % 10 = 4,4 / 10 = 0。提取出来是 0。不是十位数,而是用个位数去除以10,结果为0。✗
选项 D:int c = (n % 10) % 10;。1234 % 10 = 4,4 % 10 = 4。提取出来是 4。这是个位,不是十位——先用 % 10 取了个位,再对个位取余,等于没做任何事。✗
分析完后,他发现只有 B 能提取出正确的十位数。
但他没有立刻选 B 就走。他论证了每一个选项。
我让他再看代码的整体结构。这道题的挖空行在 for 循环里面,而 int d = n % 10; 和 if 判断在循环外面(// L1 标记之后)。这意味着什么?
他想了想:“如果 int c 填在循环里面,那 c 在循环外面还能用吗?”
这才是这道题真正的考点——不只是"哪个表达式能提取十位",还有变量的作用域。c 在循环内声明,到了循环外面 if 里面要用它——这在实际编译中是有问题的。但题目要你选的是"填入哪个选项能让程序逻辑正确",B 是唯一正确的答案。
他第一次"自己走完了"
他开始分析第三个选项的时候,我注意到他的状态变了。
之前,他每做一步都会看我一眼,等我点头。但到第三个选项的时候,他不再看我了。他自己代入数据、自己计算、自己判断对错。
我在旁边没有说话。
他分析完四个选项,抬起头:“老师,只有 B 是对的。A 提取出了两位数,C 算出来是0,D 提取的是个位。”
我说:“那代码结构上呢?”
他又看了看:“哦,c 声明在循环里面,但 if 在循环外面用 c,作用域不对。不过题目问的是填哪个选项,那还是 B。”
他没有用排除法。他用的是"论证法"——每个选项填进去会怎样,他自己算了一遍。
这就是"一题当三题"的练习方式:不是选一个答案就结束,而是把四个选项都当作四道独立的题来做。一道选择题,完成了四倍的训练量。
然后我给了他一套新卷子。他做了。
正确率:百分百。
他看着屏幕上的成绩,对我说:“原来如此。”
这个"原来如此"和之前那个"懂了"完全不同。之前那个"懂了"是我讲完方法后他说的——那是被动接收后的错觉。这个"原来如此"是他自己用正确率证明给自己看之后说的——那是主动验证后的确信。
两次"懂了"之间,他走了完整的路:从假信号,到定位误解,到搭台阶,到放手暴露,到教方法,到自己验证,到真信号出现。
⚡ 第五部分:“一题当三题”——证明错误法
回到上面那道四叶玫瑰数的题。他分析了四个选项,实际上做了四件事:论证 A、C、D 各错在哪,再确认 B 为什么对。一道题,四倍的训练量。这个方法,我管它叫**“一题当三题”**。
这个方法不只用在选择题上。我带学生做代码阅读题时也用:
- 这段代码,如果输入是
n=3,输出是什么?(正向模拟) - 如果输入是
n=0,会怎样?(边界探测) - 如果我把循环条件从
i<n改成i<=n,结果会变吗?(反事实推演)
三个问题问完,一道代码阅读题变成了三道。学生不是在"做题",而是在"拆题"——把一道题从不同角度拆开来看。
说实话,这个方法不全是我在教学中发明的。它也是我自己自学时候常用的方式。我自学的时候,遇到一道好题,不会做完就过。我会问自己:如果条件改一下呢?如果数据极端一点呢?如果换个方法做呢?
一题当三题来做,事半功倍。
这个方法的核心逻辑是:不要满足于"选出答案",要追求"理解为什么是这个答案"。 选出答案是识别,理解为什么是提取。前者让你通过考试,后者让你真正掌握。
而当你习惯了一题当三题,你会发现一件事:你不再需要老师来告诉你"你懂没懂"。 因为你自己就在验证自己——每论证一个选项为什么错,你都在确认自己的理解是对的。
这就是自我验证的开始。 🌱
💻 第六部分:编程给了一件武器——直接验证
说了这么多方法,其实编程这件事有一个其他学科很难具备的优势:
它的验证是直接的。
写完代码,运行一下,输入几组数据,看输出对不对。对就是对,错就是错。不需要等老师批改,不需要查答案对照表,不需要猜"我这样想对不对"。
这个优势太重要了。因为自我验证的前提是:学生能自己拿到"对或错"的反馈。
数学题做完了,你得翻答案。答案是"42",你写的是"43",你知道自己错了,但你知道为什么错吗?不一定。你得看解析,甚至问老师。
但编程不一样。代码跑出"43"而不是"42",你可以自己动手:在循环里加一行 cout << i << " " << sum << endl;,把每一步的中间结果打印出来,亲眼看到程序在哪一步跑偏了。
你不是在"等别人告诉你对不对",你是在"自己发现哪里不对"。
这就是为什么我在教学中反复强调"运行代码"这件事。不是为了看结果对不对,而是为了让学生养成自己验证自己的习惯。
| 验证方式 | 谁来判断 | 依赖 |
|---|---|---|
| 老师说"对了" | 教练 | 外部 |
| 考试得分 | 评分系统 | 外部 |
| 运行代码看输出 | 学生自己 | 内部 |
| 草稿模拟对照样例 | 学生自己 | 内部 |
| 证明错误法 | 学生自己 | 内部 |
从上到下,依赖从"外部"变成"内部"。当学生学会用运行代码、草稿模拟、证明错误来验证自己的时候,他就不再需要教练来告诉他"你懂没懂"——他自己知道。
这就是标题里说的"自我验证中形成自我激励"。激励不来自外部的表扬,而来自内部的确认:我自己证明了我是对的。 这种确认不需要任何人的许可,它自己就能产生力量,驱动他继续往前走。 🔥
🌉 结语:两个"懂了"之间
回到文章开头的两个学生。
第一个学生(转学生),那节课我没有追求他马上学会。我用了生活里的例子重建概念,画了流程图和思维导图帮他建立知识图谱,然后建立了一条信息交流通道——让他知道"没懂就说出来"。然后我给了他消化时间。
后来几周,他开始主动问我:“老师,那个抽屉的例子,变量类型是不是就是抽屉的大小?”
他开始自己提问了。这就是学习状态被激活的信号。 🌱
第二个学生(GESP),从"几乎全错"到"百分百正确",从"假的懂了"到"真的原来如此"。中间经历了逐句追问定位误解、草稿模拟搭台阶、放手暴露错觉、证明错误法教方法、独立验证出真信号。
他开始自己验证了。这就是自我验证闭环的完成。 ✅
两个学生,两种路径,但终点是一样的:从"老师说我对了所以我懂了",变成"我自己证明给自己看我懂了"。
第一个"懂了"是假的,它来自被动接收,像水面上的倒影,一碰就碎。
第二个"原来如此"是真的,它来自主动验证,像扎进土里的根,越长越深。
我的工作,就是在两个"懂了"之间,搭好那座桥。
先用追问把他从"听"拽进"想",再用小问题和草稿模拟给他台阶踩,接着放手让错觉自己暴露,然后教他证明错误的方法,最后让他自己运行代码、自己对照结果——直到他不需要我点头,就知道自己是对的。
那一刻他脸上的表情,从紧绷变成松弛,从松弛变成亮起来。
那个亮起来的瞬间,不是因为我表扬了他。是因为他自己,给自己,盖了一个章。
这就是自我激励。它不需要外部燃料,因为它自己就能燃烧。 🔥
📚 专栏回顾
- 第一篇:《从语法讲解到思维锻造:我的信奥教学实战总结》——教材设计、认知难点、表格追踪法
- 第二篇:《信息学学习之乐:思维、工具与自我对话》——计算思维、数学英语、自检习惯
- 第三篇:《从"无从下手"到"拿下大题"——一套完整的解题教学闭环》——五步闭环法、警惕答案记忆、学会提问、可视化演算
- 第四篇:《比方法更重要的,是找到适合他的节奏》——学生分类、年龄段差异、认知架构、可持续精力管理
- 第五篇:《让学生把"思考的路"走完,比走对更重要》——完成感、温故知新、先走完再优化
- 第六篇(本文):《"懂了"是最危险的信号——让他学会进入学习状态,在自我验证中形成自我激励》——能力错觉、双重检测、脚手架微操、证明错误法、自我验证闭环
如果这篇文章对你有帮助,欢迎点赞、收藏、转发。 👍
你在教学中遇到过"假懂"的学生吗?你是怎么发现的?评论区聊聊。 💬
延伸阅读
本文涉及的教学方法与认知科学概念,以下资料可供深入参考:
- 能力错觉(Illusion of Competence):Karpicke & Blunt (2011) 的经典实验证明,重读组的留存率最低但自信心最高,而自我测试组的留存率最高。详见 The illusion of competence: why rereading is not enough
- 儿童元认知发展:2026年发表于 Frontiers in Psychology 的研究(407名学生)发现,小学生在认知要求较高的任务上系统性高估自己的理解程度。详见 How text genre and question type shape comprehension calibration
- 自我决定理论(SDT):Deci & Ryan 提出的人类三大基本心理需求——自主感、胜任感、归属感——是内在动机的来源。详见 About Intrinsic Motivation from SDT
- 脚手架与渐进释放责任:Bruner 提出的脚手架理论,核心是在学生能力增长后逐步撤除支持。详见 Scaffolding in Education: A Teacher’s Guide
- GESP 2026年6月一级试卷:本文引用的第13题来自 CCF GESP官方试卷
关于作者
一名在信息学奥赛一线教学多年的教练。专注于C++编程教学、编程思维训练与教学策略研究。专栏「信奥教学手记」持续更新中,分享真实课堂案例与教学方法沉淀。
在这里插入图片描述
更多推荐
所有评论(0)