ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

大厂C/C++笔试真题复盘:网易2020校招考点拆解与避坑指南

大厂C/C++笔试真题复盘:网易2020校招考点拆解与避坑指南 网易2020校招笔试 C开发工程师正式批复盘真题拆解与避坑指南又到一年校招季后台不少读者私信问大厂 C/C 岗笔试到底考什么。正好我电脑里还存着当年参加网易2020校招C开发工程师正式批的完整复盘笔记趁着这个时间点把它整理出来。这篇文章只讲干货——从题型分布到考点拆解从编程题思路到具体的坑全部按实际考场经历还原。不管你是准备投递大厂开发岗的应届生还是想检验自己 C 语言功底的从业者这篇复盘都能帮你少走不少弯路。网易的校招笔试在互联网大厂里属于比较有代表性的题量适中、难度梯度合理、既考基础功底又考代码落地能力。2020 届正式批的这套题整体风格偏向“基础扎实型”没有特别偏门的算法但如果你对 C 语言内存模型、指针操作、经典数据结构的理解不到位很容易在选择题里连环踩坑编程题也会写得磕磕绊绊。接下来我按“整体情况—选择题解析—编程题复盘—常见问题—备考建议”的顺序逐一展开。1. 笔试整体情况与题型分布1.1 考试形式与时间分配网易 2020 校招 C 开发工程师正式批笔试采用的是在线笔试系统全程在牛客网平台完成总计时长 120 分钟题量分为两部分客观题选择题 主观题编程题。编程题支持 C/C/Java 等主流语言提交我选的是 C 语言作答。先说说实际考场上的直观感受时间其实不太够用。选择题 25 道涉及面非常广每道题平均只有不到 2 分钟编程题 3 道难度递增最后一道题我花了将近 40 分钟才把边界情况调完。建议后来人拿到试卷后先花 2 分钟通读全卷把编程题按难度排序先做自己有把握的不要在一道选择题上死磕。具体题型分布大概是这样的题型题量分值占比建议用时单选题15 道30%30 分钟多选题10 道25%20 分钟编程题3 道45%70 分钟1.2 考察范围与考点分布从考点覆盖来看这套笔试题目大致可以分成四个板块C 语言基础与内存管理、数据结构与算法、操作系统与 Linux、计算机网络。其中 C 语言基础占比最大这与岗位要求直接相关——作为 C 开发工程师语言本身的细节掌握程度是筛选的第一道门槛。我统计了一下自己当时的错题分布C 语言指针和内存相关错了 2 道操作系统进程线程相关错了 1 道多选里网络协议错了 1 道。整体来看这套题出得比较“正”没有偏题怪题但恰恰是这种“正”会把基础不牢的人筛得明明白白。2. 选择题考点深度拆解2.1 C 语言基础与内存管理这次笔试的“重头戏”C 语言基础在选择题里占了将近一半其中指针与内存管理是绝对核心。我记得特别清楚的一道题#include stdio.h #include stdlib.h void test(char *p) { p (char *)malloc(100); } int main() { char *str NULL; test(str); strcpy(str, hello); printf(%s\n, str); return 0; }问程序运行结果是什么。选项包括输出 hello、编译报错、运行时崩溃、输出乱码。这道题的考点是值传递与地址传递的区别。在 C 语言里函数参数默认是按值传递的test(str)传入的是str这个指针变量的拷贝函数内部p malloc(100)修改的是形参p的指向实参str仍然为 NULL。所以strcpy(str, hello)本质上是向 NULL 地址写数据程序必然崩溃。要改正确要么传递指针的指针void test(char **p)要么让函数返回指针。这个知识点可以说百考不厌我在后续面试中也被问过多次变体。另一道让我印象深刻的题是关于sizeof和strlen的对比char arr[] hello; char *p arr; printf(%lu %lu\n, sizeof(arr), sizeof(p)); printf(%lu %lu\n, strlen(arr), strlen(p));正确答案是6 8、5 5在 64 位系统下。sizeof(arr)计算的是整个数组占用字节数包含结尾的\0所以是 6sizeof(p)计算的是指针本身的字节数64 位系统下是 8strlen只统计到\0前的字符数对数组和指针结果相同。这个考点其实反映了 C 语言一个底层逻辑数组名在大多数表达式中会退化为指向首元素的指针但sizeof是少数保留数组属性的场景之一。理解了这个本质遇到类似的题就能举一反三。2.2 数据结构与算法基础链表、栈和二叉树的经典变体数据结构相关选择题主要围绕链表、栈和二叉树展开难度适中但陷阱不少。有一道关于链表反转的多选题选项里给了四种实现片段让你选出正确的。我当时的做法是直接在草稿纸上画链表节点图逐个走一遍指针变化。这个习惯帮了大忙因为这类题单纯靠“脑补”很容易漏掉边界情况比如链表为空、只有一个节点时的空指针判断。还有一道二叉树遍历的题给出前序遍历序列和中序遍历序列要求推出后序遍历。这种题没有什么捷径就是模拟递归过程每次从先序序列中取出根节点再到中序序列中定位左右子树边界递归处理。需要注意的是题目可能给出的是拓展二叉树的序列带空节点标记那判断逻辑就要相应调整此时用#表示空节点递归的终止条件不再是区间为空而是遇到#。栈的考点多与表达式求值和括号匹配结合。2020 年这批有一道算逆波兰表达式结果的题数据结构本身不复杂但题目把运算数设计成了负数和多位数增加了字符串解析的复杂度。我建议这种题在草稿纸上先设计好状态机——数字读入、遇到分隔符入栈、遇到运算符弹出两个数运算——再看题目的输入格式是否吻合。2.3 操作系统与 Linux进程线程和常见命令的实际场景操作系统的选择题数量不多大概 4-5 道但覆盖了进程线程区别、死锁必要条件、虚拟内存、Linux 文件权限等常见考点。有一道题给了四个关于进程和线程的描述让选错误的。其中一个是“线程是资源分配的基本单位进程是调度的基本单位”——这个说法把两者搞反了正确答案应该是“进程是资源分配的基本单位线程是 CPU 调度的基本单位”。这种题纯考概念准确性没有技巧复习时多下功夫背熟即可。Linux 相关的题考察了文件权限和常用命令。有一道给出rwxr-xr--问属主、属组和其他用户分别有什么权限以及对应的数字表示。答案是 754其中属主可读可写可执行7属组可读可执行5其他用户只可读4。这种题就是送分题但我认识不少同学在r对应 4、w对应 2、x对应 1 这个对应关系上栽了跟头上考场前记得再过一遍。2.4 计算机网络TCP、HTTP 基础与常见协议的“坑”计算机网络部分题量不大主要考 TCP 协议状态变迁、HTTP 请求方法、DNS 解析流程等基础内容。网易这套题里最典型的一道是关于 TCP 三次握手和四次挥手的过程描述判断哪个选项是正确的。这里有个高频陷阱很多同学会把“断开连接需要四次挥手”理解成“客户端主动断开时每次都需要四次”实际上如果通信双方同时发起断开请求可能出现同时关闭simultaneous close的特殊情况整个流程会退化为四次还是六次要看具体时序。还有一个易错点是 HTTP 和 HTTPS 的默认端口。有同学记成 80 和 8080正确是 80 和 443。这种题本身不难但考的就是你日常积累细不细。建议复习网络时把 TCP 状态图、端口号、各层协议的关系整理成一张表考前快速过一遍。3. 编程题完整复盘3.1 编程题第一题字符串逆序输出送分题第一道编程题看起来很简单输入一行字符串逆序输出。很多人觉得这就是先用strlen拿到长度再倒序遍历一遍但实际提交时才发现坑在输入输出格式上。题目说输入可能包含空格这意味着不能只用scanf(%s)因为它遇到空格就停止读取了。我当时用了fgets配合手动去掉末尾换行来处理#include stdio.h #include string.h int main() { char buf[1024]; fgets(buf, sizeof(buf), stdin); // 去掉 fgets 读入的换行符 buf[strcspn(buf, \n)] \0; int len strlen(buf); for (int i len - 1; i 0; i--) { putchar(buf[i]); } putchar(\n); return 0; }这里有个细节值得注意fgets会连同换行符一起读入如果不处理逆序输出时换行符会被放到最前面直接导致格式错误。用strcspn找到换行符的位置并替换为\0是最稳妥的写法。这道题背后的意义在于它考察的是你能否写出健壮的处理输入输出的代码——字符串是否包含空格、缓冲区大小是否足够、换行符是否被正确吞掉。实际工程开发里这类边界处理的经验往往比“算法能力”更先被考察到。3.2 编程题第二题链表合并与去重进阶题第二题要求合并两个有序链表并去除重复元素。题目本身不算难就是一个类似归并的过程但网易在题目里加了一个限制不允许额外申请节点只能通过调整指针完成合并。这意味着你不能简单地把两个链表的 val 拷贝出来排序再重建链表必须原地操作。我的思路是设置一个虚拟头节点dummy然后用双指针遍历两个链表每次把值较小的节点接在dummy后面同时处理重复值。具体代码如下#include stdio.h #include stdlib.h struct ListNode { int val; struct ListNode *next; }; struct ListNode* mergeAndDedup(struct ListNode* l1, struct ListNode* l2) { struct ListNode dummy; dummy.next NULL; struct ListNode *tail dummy; while (l1 l2) { if (l1-val l2-val) { if (tail-next NULL || tail-val ! l1-val) { tail-next l1; tail l1; } l1 l1-next; } else if (l1-val l2-val) { if (tail-next NULL || tail-val ! l2-val) { tail-next l2; tail l2; } l2 l2-next; } else { // 相等时只保留一个两个指针都向后移动 if (tail-next NULL || tail-val ! l1-val) { tail-next l1; tail l1; } l1 l1-next; l2 l2-next; } } // 处理剩余节点 struct ListNode *rest l1 ? l1 : l2; while (rest) { if (tail-next NULL || tail-val ! rest-val) { tail-next rest; tail rest; } rest rest-next; } tail-next NULL; return dummy.next; }这段代码里有几个容易忽视的细节。第一是去重逻辑在把某个节点接入结果链之前要先判断tail-val是否和当前节点值相同相同就跳过第二是在相等去重时两个链表的指针都要向后移动否则会死循环第三是最后要把tail-next置为 NULL避免把原链表中被跳过的节点又带回来。这种题的考察重点其实是“链表的边界处理能力”虚拟头节点可以避免对空链表和头节点的特殊判断而空指针判断和指针移动的先后顺序则是链表类题目的核心。3.3 编程题第三题带权最短路径问题拉开差距题第三题是一道图论题要求在给定网格中寻找从起点到终点的带权最短路径。没有说明数据范围但从题目描述推测网格边长可能在 1000 级别。显然朴素的 DFS 会超时需要用 Dijkstra 或者带优先级队列的 BFS。由于是在线笔试环境我优先选择了 Dijkstra 最小堆实现用priority_queue每次取出当前距离最小的节点进行松弛。如果题目保证所有边权相同那直接普通 BFS 即可但 2020 这套题在路径上设了不同的消耗值所以必须上 Dijkstra。核心代码如下#include vector #include queue #include climits using namespace std; int shortestPath(vectorvectorint grid) { int n grid.size(), m grid[0].size(); vectorvectorint dist(n, vectorint(m, INT_MAX)); priority_queuepairint, pairint, int, vectorpairint, pairint, int, greater pq; dist[0][0] grid[0][0]; pq.push({dist[0][0], {0, 0}}); int dx[4] {1, -1, 0, 0}; int dy[4] {0, 0, 1, -1}; while (!pq.empty()) { auto [d, pos] pq.top(); pq.pop(); int x pos.first, y pos.second; if (d dist[x][y]) continue; for (int i 0; i 4; i) { int nx x dx[i], ny y dy[i]; if (nx 0 || nx n || ny 0 || ny m) continue; int nd d grid[nx][ny]; if (nd dist[nx][ny]) { dist[nx][ny] nd; pq.push({nd, {nx, ny}}); } } } return dist[n-1][m-1]; }这题最大的坑在于很多人拿到题后直接写 BFS但没有看到路径权值不一致这个关键细节。如果你交上去才发现用错算法重新写一份完整 Dijkstra 的时间成本非常高。所以拿到编程题之后一定要先花 30 秒确认输入数据的特性是否有负权边、边权是否一致、数据范围多大再决定用什么算法。我这次在第三题上踩的一个坑是priority_queue默认是大顶堆必须手动传入greater把它改成小顶堆。这是一个非常典型的 C 使用细节出错的瞬间会在考试压力下放大成十几分钟的排查时间。4. 笔试中的经典陷阱与避坑指南4.1 指针与内存管理的三个“连环坑”在选择题和编程题里指针相关的内容至少出现了 5 次。我总结出三个高频连环坑第一是栈区返回局部变量地址char* getString() { char str[] hello; return str; }str是函数内的局部数组存储在栈上函数返回后该内存已经被回收主调方再去解引用就属于未定义行为。轻则输出随机值重则崩溃。如果真想返回字符串应该用static char str[]或malloc分配堆内存。第二是内存泄漏malloc之后忘记free尤其在循环里多次分配内存但不释放笔试题目会把这个场景包装成“以下代码有什么问题”。2020 年这套选择题里就有一道题目写的malloc后直接return问是否会导致内存泄漏——答案是肯定的而且即使程序退出后操作系统会回收内存但在长时间运行的服务里这就是致命的。第三是sizeof 与字符串长度混淆前面已经说过sizeof(arr)和strlen(arr)的值往往不一致。很多同学在写程序时用sizeof(str)作为strcpy的长度参数导致字符串拷贝越界。实际上strcpy会自动处理\0你需要保证的是目标缓冲区足够大而不是手动传长度。4.2 编译链接过程中容易被忽略的细节网易这套笔试里有一道关于static关键字的题选项涉及 static 修饰局部变量、全局变量和函数的不同效果。这里有个容易混淆的点static修饰局部变量时它的生命周期变为整个程序运行期但作用域仍然只在函数内部static修饰全局变量时它的作用域被限制在当前源文件内外部文件无法通过 extern 引用。还有一个关于const的题问const char *p和char * const p的区别。前者是“指向常量的指针”指针本身可以修改但不能通过它修改指向的值后者是“指针常量”指针本身不能修改但指向的值可以通过它修改。这个经常有人搞反可以这样记const修饰的是它右边紧挨着的类型const char *p中const修饰char而char * const p中const修饰p本身。4.3 在线笔试环境下的时间管理与提交策略在线笔试和平时在自己电脑上写代码有很大区别不能本地调试、不能随时查文档、编译错误会直接扣分。我这次踩过的一个直接教训是——编程题的输入输出格式没有百分百按示例格式排查导致第一题白白浪费了一次提交机会。在线笔试平台的判题逻辑通常是多个隐藏测试用例每一个用例都严格比对输出。所以提交前一定要检查末尾是否有多余空格或换行、输出大小写是否完全一致、浮点数精度是否保留到指定位数。建议在本地测试时手动构造几组特殊输入比如空字符串、只有一个字符、最大长度、包含空格和特殊字符的串。时间分配上我的建议是“选做结合”选择题 50 分钟内必须完成无论会不会都先选一个答案不要空着碰到多选题拿不准时优先选择你最有把握的选项并遵循“漏选得部分分错选不得分”的规则尽量保证稳拿分编程题按照“第一题 15 分钟、第二题 25 分钟、第三题 30 分钟”的节奏去卡时间如果第三题超过 30 分钟还没有清晰思路果断回来检查前两题的边界。5. 复盘总结与备考建议5.1 面向大厂 C/C 岗位的复习路线如果你准备的是网易、腾讯、阿里、字节这类大厂的 C/C 开发岗笔试我的建议是复习路线分三步走。第一步是语言基础扫盲重点吃透指针、数组、结构体、内存布局、堆与栈的区别、static/const/extern关键字的语义、位运算、宏定义与内联函数的区别。推荐把《C 程序设计语言》中关于指针的章节重读一遍配合做课后题。第二步是数据结构与算法专项核心覆盖数组、链表、栈、队列、哈希表、二叉树、堆、图的最短路径和最小生成树、排序与查找、回溯算法。不必追求极端难题但经典题目要能做到“闭眼默写”——链表反转、合并有序链表、二叉树遍历递归迭代、快速排序/堆排序、Dijkstra、二分查找的边界处理这些是笔试编程题的高频素材。第三步是系统知识串讲包括操作系统进程线程、同步互斥、死锁、虚拟内存、页面置换、计算机网络TCP/UDP、三次握手/四次挥手、HTTP/HTTPS、DNS 流程、Linux 基础文件权限、进程管理命令、管道与重定向、常用文本处理命令。这部分以选择题为主复习时多做笔记反复记忆。5.2 考前一周的“冲刺清单”考前一周不建议再学新知识而是做三件事第一是刷近两年的真题牛客网上有大量大厂笔试原题每套题都按真实考试时间限时完成训练答题节奏第二是整理错题本把易错的知识点、没看清的题目条件、没想明白的边界情况记录到一个文档里每天早中晚各快速翻一遍第三是模拟编程题环境在牛客或 LeetCode 上做 3-5 道中等难度的题提交过程严格按照“读题→设计算法→写码→构造测试用例→提交”的顺序完成。还有一个细节在线笔试前一定检查本地网络和浏览器兼容性提前 30 分钟进入候考页面。2020 年那次笔试我所在的考场群里有同学因为浏览器拦截了弹窗导致编译器无法弹出白白浪费了 10 分钟考试时间。5.3 笔试通过后的面试衔接准备笔试通过只是第一步面试环节对 C 语言的考察会更加细化。以我后续的面试经验来看网易的技术面一般会追问你笔试里某道编程题的时间复杂度和空间复杂度是多少能不能优化某个内存泄漏场景如何排查进程和线程在实际应用中的取舍是什么所以笔试结束后不要马上松懈而要把每一道错题都当成深入复习的入口。我的个人习惯是笔试结束后两小时内趁着记忆还新鲜把整个考试遇到的题目、自己的解法、卡壳的位置全部复盘写进笔记。这份笔记会在后续面试复习中反复用到远比考后两周再回忆来得完整。5.4 关于心态与长期积累的一点体会回到这套笔试本身我最大的感悟是网易 2020 校招 C 开发工程师正式批的题目并没有追求“难倒所有人”而是在筛选那些真正写过代码、踩过坑、对底层机制有好奇心的人。选择题里的内存问题、编程题里的链表边界处理本质上都是工程中经常遇到的真实场景。我始终觉得刷题是必要的但刷题之后一定要回归到“理解原理”上来。为什么数组名在大部分表达式中会退化成指针为什么Malloc的内存必须free为什么 Dijkstra 要求边权非负这些问题想明白了笔试面试自然游刃有余。最后分享一个小技巧从这次笔试开始我养成了用“费曼学习法”复盘每一道错题的习惯——每道错题都先假装自己是一个老师要把它讲给完全不会的人听。讲到卡壳的地方就是知识盲区回头查资料再讲一遍。这个方法看起来慢但对打牢 C 语言底层功底特别有效后续在笔试和面试中都帮我拿下了不少关键分数。希望这篇复盘能帮正在备战的你少踩几个坑也欢迎大家考完回来交流真题变体。
返回列表