资讯动态

360春招C++笔试客观题解析:从指针到STL的基础能力体检

发布时间:2026/8/31 5:20:26 来源:尧图企业网站定制
我保存了2018年360春招C开发工程师岗位的笔试客观题当时做完最大的感受是这卷子不考偏题怪题就是实打实考基础。C开发岗的客观题看起来是选择题实际上是把程序员的基本功掰开揉碎了放在一个个小场景里让你判断。指针、内存、字符串、排序、面向对象、操作系统、网络这些点全是日常写代码要用的东西。准备校招C岗位的同学、想系统查漏补缺基础知识的开发者甚至带新人的技术组长都可以拿这份笔试合集当一面镜子照一照自己的底子是不是真的扎实。我把这套题重做了一遍再把每类题背后的出题逻辑、解题套路、容易踩的坑全部整理出来尽量还原当年的考点分布。下面进入正题。1. 这份卷子到底在考什么题型设计与出题意图拆解1.1 客观题不是知识点检索而是基础能力体检先说一个很多同学容易误解的地方笔试客观题不追求你“背了多少知识点”它考的是“你有没有在实际编程中被这些知识点坑过”。360作为网络安全起家的公司C开发岗的候选人会被要求具备很强的底层思维所以客观题特别喜欢考“这段代码输出什么”“这个表达式值是多少”“这个程序会不会崩溃”这类问题。表面上是选择题实际上每题都是一段微型的代码排错演练。从题型结构上看当年的卷子以单选题和多选题为主偶尔穿插判断题。单选题覆盖C语言基础、C语法特性、数据结构与算法复杂度、操作系统概念、网络协议基础多选题则集中在C的语言细节上比如const的多种用法、构造与析构的顺序、STL容器的迭代器失效问题等。多选题是丢分重灾区因为少选多选都不得分这就要求你对知识点的掌握必须“精确到边界条件”而不是模模糊糊知道个大概。1.2 出题人真正想考的是三层递进的能力我把这套客观题的考点拆开以后发现它其实是在按三个层次筛选候选人。第一层是“语法敏感度”。这个层次考的是你有没有在一行行代码里被编译器教训过。比如sizeof和strlen的区别、指针自增自减的运算优先级、二维数组的指针传递、static关键字在不同位置的语义差异。这些题目如果只靠背书很容易记混但如果平时写代码时真的踩过这些坑一眼就能看出答案。第二层是“算法基本功”。360的笔试不会在客观题里出太难的手写算法但会通过选择题来检验你对常见算法的理解深度。比如排序算法的稳定性、不同排序在最好最坏情况下的时间复杂度、二分查找的边界条件、字符串逆序和链表反转这类经典问题的空间复杂度。这类题的目的不是让你表演算法而是确认你在真正设计系统时能选对数据结构、估算出性能。第三层是“系统全局观”。C开发工程师写的不只是业务代码还要跟内存、线程、网络、磁盘打交道。所以客观题里一定会掺入操作系统和计算机网络的选择题比如进程和线程的区别、死锁产生的四个必要条件、TCP握手过程、数据库索引的数据结构。这些知识在笔试阶段不会考得太深但它决定了你之后看线上问题、做性能优化时能不能找到方向。2. C/C核心考点逐项拆解从语法到内存2.1 指针与数组笔试里最经典的分水岭指针和数组几乎是每一份C/C笔试题里都绕不开的内容360这套题也不例外。出题人特别爱把指针和数组放在同一个表达式里考察你到底理解的是“类型”还是“地址”。我捡一道典型的回忆版题目说int a[5] {1, 2, 3, 4, 5}; int *p a 1; printf(%d %d, *(p 1), *(a 3));这道题没有太多陷阱答案是3和4。但它的变体就开始迷惑人了比如把p声明成int (*p)[5]或者把a传进函数后问sizeof(a)等于多少。很多人在这种地方丢分是因为没有分清“数组名是常量地址”和“数组名在表达式里退化为指针”这两件事。数组名在绝大多数表达式中会退化为指向首元素的指针但在sizeof和操作符下不会退化。所以sizeof(a)是20而sizeof(a0)是864位系统下指针大小。另一个高频点是二维数组的指针操作。比如声明int b[3][4]那么b的类型是int (*)[4]b1跳过的是一行也就是16个字节而不是4个字节。这种题你光凭“地址是多少”很难算对必须建立起“指针的类型决定步长”这个观念。我建议你复习时自己在纸上画一画内存布局把b、*b、b[0]、b[0][0]这四个表达式打印出来对比一次胜过于背十道题。2.2 字符串函数与逆序输出小题里的大文章当年的卷子里有一类题看起来很简单比如“写出字符串逆序输出的实现”但在选择题里它会被包装成“下面哪种实现方式是正确的”。网络上关于“字符串逆序输出C语言”的讨论非常多说明这确实是笔试常客。核心考点有三个原地逆序还是新开空间、strlen的返回值类型、逆序后是否需要手动补\0。一个常见的错误实现是这样的void reverse(char *s) { int len strlen(s); for (int i 0; i len / 2; i) { char tmp s[i]; s[i] s[len - 1 - i]; s[len - 1 - i] tmp; } }这个实现没问题。但如果你把循环条件写成i len / 2当字符串长度为偶数时中间两个字符会被交换两次等于白交换一次字符串变回原样。这种边界条件就是选择题喜欢的坑。另一个坑是有人会写出这样的代码char *reverse(char *s) { int len strlen(s); char *p (char *)malloc(len); for (int i 0; i len; i) { p[i] s[len - 1 - i]; } return p; }这段代码有两处致命问题一是malloc(len)没有为\0留空间越界写入二是没有检查malloc的返回值。如果题目问“这段代码有什么问题”正确答案就是“内存越界”。这类题目考查的其实是你写C代码时有没有养成“给字符串结尾留位置”的下意识习惯。顺带提醒一下strcpy、strcat这类不安全函数也是笔试常客选项里经常会出现strncpy是否能替代strcpy的讨论。strncpy并不是万能的它不会自动追加\0如果源字符串长度等于n目标缓冲区就不会有结尾符。这个细节很多工作两三年的同事都会记错但在笔试里它就是一道实打实的多选题。2.3 排序与查找复杂度判断是送分题还是陷阱题排序算法在客观题里主要考复杂度和稳定性很少让你完整手写。但我发现这道题有一个规律越是常见的算法越容易出“反直觉”的选项。比如快排的平均时间复杂度是O(n log n)最坏是O(n^2)这个大家都知道。但选择题里经常会把这个信息跟“快排是否稳定”混在一起很多同学一紧张就会选错。我把高频排序算法的关键属性整理成一个表排序算法平均时间复杂度最坏时间复杂度空间复杂度是否稳定冒泡排序O(n^2)O(n^2)O(1)稳定快速排序O(n log n)O(n^2)O(log n)不稳定归并排序O(n log n)O(n log n)O(n)稳定堆排序O(n log n)O(n log n)O(1)不稳定选择排序O(n^2)O(n^2)O(1)不稳定插入排序O(n^2)O(n^2)O(1)稳定注意冒泡排序和插入排序是稳定排序这个不难记。堆排序和快排不稳定原因是它们都存在远距离交换元素的情况会破坏相同元素的相对顺序。选择题常会这样出给出一组数据问“经过某排序算法第一趟后结果是什么”。这时候你必须知道每一趟排序结束后数据的局部特征。比如冒泡排序第一趟结束后最大的数一定在末尾快排第一趟结束后基准元素一定在它最终应该在的位置上。记住这些“一趟特征”比背代码管用得多。另外二分查找的边界条件也很常考。网上关于“字符串逆序输出C语言”“冒泡排序C语言”的搜索热度一直很高说明这些基础点确实是笔试的刚需。二分查找我最建议你记住一种写法然后反复用左闭右闭区间[left, right]循环条件是left right更新方式是left mid 1和right mid - 1。只要固定这一种写法就不会出现死循环或者漏查边界的问题。2.4 C面向对象和STL客观题最喜欢挖的语言细节C部分的客观题是拉开差距的地方。因为C语言部分大家都会用但C的语言细节比如构造析构顺序、虚函数机制、const的各种位置、STL的迭代器失效很多人只是“听说过”没有真正在工程里验证过遇到多选题就会发懵。构造和析构顺序是选择题常客。规则其实很简单构造时先基类后派生类先成员后自身析构时顺序完全相反。但如果涉及虚继承情况会复杂一些虚基类的构造函数最先执行。当年的题目里有一道是这样考的class A { ... }; class B : public A { ... }; class C : public A { ... }; class D : public B, public C { ... };问创建D对象时A的构造函数执行几次。正常情况下执行两次因为D通过B和C两条路径各自继承了一份A。但如果B和C都虚继承自A那就只执行一次。这个考点非常经典也是“菱形继承”问题的核心。STL部分的考题集中在迭代器和容器选择上。比如vector在插入元素导致重新分配内存后所有迭代器都会失效deque在中间插入元素会使所有迭代器失效list和map在插入元素时不会使已有迭代器失效但删除元素时只有指向被删除元素的迭代器失效。这类题没有捷径就是需要你把每种容器的底层实现连续内存、链表、红黑树和迭代器失效规则对应起来记。另外auto_ptr在C11之后已经被废弃当年的笔试题还在考它的所有权转移语义。现在复习的时候建议把它升级为unique_ptr、shared_ptr、weak_ptr的考察。智能指针的考题往往会结合“循环引用”出多选shared_ptr互相引用会导致内存泄漏解决办法是把其中一个改成weak_ptr。3. 笔试中的系统与网络知识C工程师的地基3.1 进程、线程与内存分区C开发工程师写的程序最终要跑在操作系统上所以笔试里一定会有操作系统相关题目。这一类题不是死记硬背而是跟你写代码时的选择紧密相关。比如“进程和线程的区别”最常见的正确表述是进程是资源分配的基本单位线程是CPU调度的基本单位同一进程的线程共享地址空间而进程之间地址空间相互独立。跟C关系最密切的是内存分区问题。选择题会给你一段代码问其中的变量分别存储在哪个区域全局变量和static变量存储在静态区也叫全局区函数内定义的局部变量存储在栈区malloc或new出来的内存在堆区字符串字面量等只读数据存储在只读常量区。一个比较隐蔽的考点是static局部变量存储在静态区生命周期是整个程序运行期间但作用域仍然是函数内。这个知识在“构造函数执行顺序”里也会有变体。比如一个函数内有static对象第一次调用时执行构造函数程序结束时才执行析构函数。如果面试官喜欢延伸会接着问“静态局部变量是否线程安全”答案是不安全初始化时在多线程环境下存在竞争。new和malloc的区别也是客观题高频中的高频。我建议你从四个维度去记一是new是运算符malloc是库函数二是new会调用构造函数malloc不会三是new返回类型安全的指针malloc返回void*四是失败时的行为不同new抛出bad_alloc异常malloc返回NULL。多选题特别喜欢把“失败返回NULL”和“new也会返回NULL”混在一起就是考验你清不清楚C98时代new(nothrow)的特殊写法。3.2 计算机网络与操作系统高频点网络部分在客观题里不会出得太深但基本概念必须拿分。TCP三次握手几乎是必考的核心不是背“SYN、ACK”这几个词而是理解为什么是三次而不是两次因为三次握手能确认双方的收发能力都正常并且能避免历史重复连接请求对服务端造成资源浪费。选择题里经常出现的干扰选项是“两次握手也能建立连接”这个表述只有在不考虑历史重复报文和资源分配的情况下才勉强成立在标准答案里必须判错。死锁的四个必要条件互斥、持有并等待、不可剥夺、循环等待也是老面孔。题目会给你四个描述让你选出哪几个属于死锁的必要条件。这个只要背住就行但要注意区分“循环等待”和“等待图中有环”的关系死锁一定有环但有环不一定死锁因为持有资源的线程可能马上释放资源。数据库题在C岗笔试里不会占太多比例但常常会出现“索引用了什么数据结构”这道题。正确答案是B树。B树为什么适合做数据库索引因为它可以有效降低树高减少磁盘IO次数同时所有数据都存储在叶子节点方便范围查询。这个知识点如果你只看结论不看原因遇到变体题比如“为什么不用红黑树”就会答不上来。3.3 Linux与编译链接的基础考查很多同学容易忽略的另一个客观题来源是Linux基础。C开发工程师日常要在Linux环境下编译、调试所以卷子里偶尔会出一些命令题。常考的无非是grep按行匹配文本、ps查看进程、top动态查看系统负载、gdb调试程序、nm查看符号表、objdump反汇编。这些题本身不难难的是你平时根本没在Linux下工作过纯靠背选项容易记混。编译链接的过程也是一个高频考点预处理宏展开、头文件包含、编译生成汇编代码、汇编生成目标文件、链接合并目标文件和库。选择题里会说“下列哪个阶段处理#define宏”答案是预处理阶段。还有一道很经典的题-static静态链接和动态链接的区别。静态链接会把库代码复制进可执行文件启动快但文件大、更新库需要重新编译动态链接在运行时加载共享库节省内存但可能出现“找不到动态库”的问题。现在容器化部署越来越普及这个考点在面试环节还可能被追问成场景题。4. 实操刷题时如何拆解一道选择题拿到90%正确率4.1 选择题的标准化解题流程很多人做选择题是“凭感觉”。但你要知道笔试是限时的而且有些题是故意“挖坑”的靠感觉做题等于把命运交给运气。我给自己定的流程是四步看选项、判类型、带边界、快排除。第一步先看选项而不是先看题干。因为客观题的正确选项往往是“最正确”的那一个而不是“绝对正确”的那一个。把四个选项扫一遍如果发现有两个选项说的是同一件事、只是表述不同那正确答案大概率在这两个之间剩下的两个是陪跑。第二步判断题目类型这是编译器行为题、算法复杂度题还是系统概念题不同题型的做题策略不一样——算法题可以手推小数据验证系统概念题得靠定义判断编译器行为题必须代入“如果是我写这段代码会怎样”的经验。第三步往极端情况下带边界值。比如题目问“以下哪种操作会导致vector迭代器失效”你就往“重新分配内存”这个最典型的情形上靠。第四步排除明显干扰项把正确答案锁死。这个流程看起来简单但实际做题时很多人会跳过“看选项”和“带边界值”。尤其是多选题必须一个选项一个选项地验证不能用排除法排除到最后一个就草率选中因为多选题正确答案的个数不固定有时候四个全对。4.2 客观题的时间分配与错题整理方法按照一份笔试45到60分钟的客观题量来算我建议你单选题控制在每题1分钟以内多选题每题1分半到2分钟。如果一道题超过2分钟还没有思路立刻跳过先把会做的全部做完再回头啃硬骨头。360的笔试一般不会因为一道题卡住让你交白卷但因为心态爆炸导致后面简单题也出错的情况却很常见。刷题之后的整理比刷题本身更重要。我的方法是这样准备一个错题本不抄原题把错题转化成一个“知识点挖坑点”的组合。比如错误选项是“strncpy总是自动追加\0”你在错题本上记下“strncpy在n等于源字符串长度时不追加\0”。再比如错题是“快排第一趟后基准元素一定在正确位置”你记下“快排一趟特征”。这样一来第二遍复习的时候你只需要看几十条这样的“坑位记录”半小时就能过完一遍比重新做一遍题高效得多。另外我特别建议你整理一张“选项高频陷阱清单”。比如sizeof和strlen混用、指针自增与取值运算符的优先级、i和i的返回值区别、const int *和int * const的区别、delete和delete[]混用。这张清单刷题时会越滚越长到考前看一遍稳定提分。4.3 模拟真实笔试环境的检查清单我当年吃过一个亏线上笔试时编辑器没有自动补全代码题手写代码还好客观题倒是没什么影响但编译环境切换特别费时间。所以正式笔试前务必先调试好在线笔试平台熟悉它的代码编辑区、编译按钮、交卷确认流程。有些平台还支持本地IDE写代码再贴上去但如果平台禁用了复制粘贴你就得提前适应网页编辑器。时间安排上我的建议是客观题和编程题分开看待。先把客观题全部做完再做编程题。因为客观题涉及的知识面很杂越到后面思维越疲劳先解决客观题能保证基本盘。编程题通常分值大但也很容易卡壳把它放到后面至少不会出现“客观题没时间做编程题也没做出来”的两头空局面。5. 高频错题与避坑实录我自己踩过的那些坑5.1 五个最常见的丢分点我直接整理成表我在重做这套题时把最容易丢分的知识点挑了出来。不敢说覆盖全部但下面这几类是我自己以及身边同事当年都栽过的。考点常见错误理解正确结论sizeof 和 strlenstrlen返回数组大小strlen返回字符串长度不含结尾\0sizeof在编译期计算含结尾符指针自增与取值*p等价于(*p)*p先取*p再指针自增(*p)是先取值再让值自增const修饰const int *p和int const *p不同两者等价都表示指向常量的指针int *const p才表示指针本身是常量静态变量static局部变量作用域扩展作用域不变生命周期扩展到整个程序运行期间容器迭代器vector插入元素后所有迭代器一定失效只有插入导致重新分配空间时所有迭代器失效未重新分配时指向插入位置之后的迭代器失效这里面*p那道题尤其经典。C笔试里几乎每份卷子都会出每次都有不少人做错。它的优先级规则是后置优先级高于*所以*p等于*(p)先返回*p的值再把指针向后移动一位。如果想先让指针移动再取值应该写*p。这种语言细节不写代码的人根本不会留意但只要你在调试或遍历数组时写过类似的表达式基本秒答。5.2 遇到有歧义的题怎么选才不亏分有些笔试题本身存在争议比如“运算符优先级”相关题目在不同编译器下可能出现不同行为或者某道多选题在不同教材里表述不一样。遇到这种情况我给自己定了一个原则按标准工程实践来选不按犄角旮旯的奇技淫巧来选。具体做法是如果某个选项的描述在绝大多数情况下成立只有极端的未定义行为下不成立那这道题的出题意图多半是“考察你懂不懂未定义行为”而不是“考察这个选项是否绝对正确”。比如“i i的值是多少”这种题直接选“未定义行为”或者“不要写这种代码”往往就是正确方向。如果你在同一个选项里看到了“一定”“肯定”“总是”这种绝对化词并且这个说法涉及语言标准未明确规定的区域那这个选项大概率是错的。还有一点多选题拿不准时宁可少选不要乱选。很多在线笔试平台的规则是“少选得部分分错选零分”这时候保证“选上的选项都是对的”比“凑齐所有正确选项”更重要。这个策略并不矛盾因为少选只是少得分错选直接归零。写在最后的一点体会重做这套题之后我最大的感受是笔试客观题看似在考记忆实际上考的是你平时写代码时有没有建立起“被坑过”的条件反射。指针越界、字符串缺结尾符、迭代器失效、内存泄漏这些坑在笔试里是选择题在真实项目里就是线上事故。2018年的题目到现在已经过去好几年但基础考点没有变甚至可以说现在写C服务端遇到的大部分疑难杂症根子都还是这些基础概念没吃透。如果你正在准备类似的笔试我的建议是别光背题动手把每个考点写成小代码跑一遍。比如const的各种组合、strncpy的结尾符行为、vector和list在不同操作下的迭代器变化这些用几行代码验证一下印象比看十道题都深。基础越扎实笔试题越简单——这是我在这么多年写代码、带新人、刷题库之后最想告诉你的一句话。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价