十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

东土科技秋招笔试深度解析:C/C++与嵌入式核心考点全复盘

东土科技秋招笔试深度解析:C/C++与嵌入式核心考点全复盘 1. 秋招笔试整体印象东土科技在找什么样的人2023年秋招季我投了东土科技的软件开发岗笔试做完最大的感受是这家公司不玩虚的题目很实在几乎每一道题都在问“你毕业后能不能直接上手干活”。东土科技做工业互联网和智能制造出身旗下还有操作系统、工业通信、边缘计算这些业务线所以软件开发岗的笔试内容明显偏向底层、偏向C/C、偏向嵌入式场景跟互联网大厂那种“八股文脑筋急转弯”的风格差别很大。先说整体印象笔试时间120分钟题量不算特别大但覆盖面很广包含选择题、判断题、简答题和两道编程题。选择题主要集中在C语言基础、数据结构、操作系统、计算机网络简答题涉及内存管理、进程通信、实时性设计这些嵌入式软件开发的经典话题编程题则考察链表操作和字符串处理。从题型设计能看出东土科技筛选的不是“背题高手”而是真正理解计算机系统底层逻辑的人。毕竟工业通信设备和实时控制系统的软件容错率极低一个内存泄漏在消费级App里可能只是卡顿在工业现场就是设备停机和产线事故。另外我注意到一个细节笔试题里多次出现“嵌入式软件开发”相关场景比如中断处理、实时操作系统任务调度、共享内存通信这与东土科技在工业互联网领域的布局高度吻合。如果你准备投这家公司建议重点复习嵌入式软件开发面试题中常见的那些考点而不要把精力都花在Spring Cloud、MySQL优化这些互联网后端内容上方向真的不对。2. 笔试科目拆解C/C和数据结构才是重头戏2.1 C语言基础指针、内存、关键字一个不落东土科技的C语言题目难度中等偏上但考察点非常集中。选择题里至少有三分之一在考指针和内存比如“以下代码是否存在内存泄漏”“指针数组和数组指针的区别”“const修饰指针的三种情况分别表示什么”。这些题目如果你在大学里只是“背过概念”而没有实际写过底层代码很容易栽跟头。让我印象最深的是一道关于“野指针”的题目它考察的不只是定义而是给了一段实际代码让你判断哪一行产生了野指针。代码逻辑大概是函数返回局部变量地址、释放内存后未置空指针、指针越界访问数组。这三个坑全部埋在同一段代码里要求逐行分析。这其实就是在模拟真实嵌入式开发中常见的指针使用错误平时写业务代码很少遇到但做底层驱动或者通信协议解析时几乎天天跟这些打交道。注意备考东土这类偏底层岗位的笔试不要只看概念一定要自己动手写代码验证。我强烈建议你复习时把C语言经典面试题中关于指针和内存的部分全部手敲一遍观察运行结果和内存变化比单纯背书有效十倍。2.2 数据结构链表和栈是考察重点数据结构部分东土科技没有考那些偏门的高级数据结构重点放在了链表、栈、队列、二叉树。选择题中出现了“用两个栈实现队列的最小时间复杂度”“判断链表是否有环的算法复杂度”“二叉树前序遍历和中序遍历还原二叉树”这些经典题目难度跟《剑指Offer》和LeetCode简单题持平。但真正有区分度的是编程题其中一道就是“反转链表要求使用递归和非递归两种方式实现”。这道题很能看出基本功非递归反转链表只需要三个指针依次翻转大部分人都能写出来但递归版本考察的是对函数调用栈和递归终止条件的理解。我当时先写了非递归版本然后又写递归版本还在注释里补充了两种方式的时空复杂度对比这应该算是一个加分项。另一个数据结构相关的简答题是关于栈在函数调用中的作用要你解释“函数调用过程中栈帧如何建立和销毁、局部变量存放在哪里、递归为什么会溢出”。这其实是在考察计算机系统基础知识跟嵌入式软件开发岗位特别契合因为嵌入式环境里栈空间往往很小动辄只有几KB一个不小心递归深度过大就会导致系统崩溃。2.3 C与STL问得不多但问得深C相关的题目占比不大但只要出现就有一定深度。选择题里有一道关于“vector扩容机制”的问的是“vector在内存不足时如何扩容旧元素如何迁移迭代器为什么会失效”。还有一个简答题问“RAII是什么在C中如何实现举例说明它在资源管理中的作用”。这些属于嵌入式软件开发面试题里比较常见的C考点。RAII那道题我当时回答的思路是RAII的核心思想是把资源的生命周期绑定到对象的生命周期构造函数中获取资源析构函数中释放资源这样即使发生异常栈上的对象也会自动调用析构函数释放资源不会泄漏。我用智能指针作为例子还提到了C11之后的unique_ptr、shared_ptr、weak_ptr各自的使用场景和底层原理特别是shared_ptr的引用计数为什么是线程安全的、控制块里存了什么信息。这种“从现象到原理”的回答方式比较加分。3. 操作系统与网络通信嵌入式软件开发的核心战场3.1 进程线程与内存管理问你的是“怎么用”而不仅是“是什么”操作系统部分的笔试题目明显偏向实用。进程与线程的区别、进程间通信方式、死锁产生的四个必要条件这些属于送分题只要认真复习过都能答上来。但后面的简答题就有点意思了它问“在多线程环境下如何保证共享数据的安全性分别说明互斥锁、读写锁、自旋锁的适用场景”。这道题如果只是回答“互斥锁用于保护临界区读写锁适合读多写少自旋锁用于短临界区保护”那只能算及格。要想答得漂亮需要补充更多细节互斥锁在锁被占用时线程会睡眠并触发上下文切换而自旋锁会一直忙等待占用CPU所以在单核处理器上自旋锁可能带来性能问题读写锁要区分读者优先和写者优先策略不同策略可能带来写者饥饿或读者饥饿问题自旋锁在嵌入式实时系统里很常见但前提是临界区执行时间远小于线程调度的开销否则白白浪费CPU时间片。内存管理方面考了虚拟内存和物理内存的映射关系、malloc底层实现、内存碎片如何产生和避免。其中malloc的底层实现这一题我详细说明了malloc在分配大块内存时如何使用mmap、小块内存时如何使用brk调整堆顶以及这两种方式各自的优缺点。还提到了嵌入式环境中常用静态内存池替代动态内存malloc因为动态内存分配带来的碎片和不确定性无法满足实时性要求东土科技做工业通信设备这类场景非常多。3.2 网络通信TCP三次握手和UDP之外的重点计算机网络部分TCP三次握手、四次挥手、TIME_WAIT状态、TCP和UDP的区别这些属于常规考点。但东土科技的笔试题目里网络部分不是孤立考察协议栈而是跟实际业务场景绑定比如“设计一个工业现场设备通信方案你会选TCP还是UDP为什么”。这种题就很考验工程判断能力。我当时回答的大致思路是工业现场通信对实时性要求高TCP的重传机制虽然可靠但可能会带来毫秒级甚至百毫秒级的延迟抖动所以很多工业实时协议选择UDP作为承载层在应用层自己实现可靠性机制。另外还提到了组播在工业通信中的应用场景比如一个主站给多个从站同时下发控制指令用UDP组播比逐一建立TCP连接更高效。3.3 实时系统与中断嵌入式软件开发必须跨过的门槛东土科技的笔试里出现了不少跟实时系统相关的题目比如“什么是硬实时和软实时”“中断服务程序ISR中哪些操作是不允许的”“如何设计一个无锁队列实现任务间通信”。这些题对没接触过嵌入式软件开发的人来说可能完全陌生但确实是东土这类公司的核心考点。我挑了其中一道印象最深的题来复盘它让你用伪代码实现一个基于环形缓冲区的无锁队列要求支持单生产者单消费者场景。这道题考察的东西非常多包括内存屏障、原子操作、缓存一致性、ABA问题。我当时的方案是用一个固定大小的数组生产者只修改写索引消费者只修改读索引两个索引都用volatile修饰并保证索引更新使用原子操作。在单生产者单消费者场景下不需要加锁就能实现线程安全的队列因为生产者和消费者修改的是不同的变量不存在竞争条件。这套方案的核心原理在于生产者写入数据后再更新写索引消费者先读取写索引再取数据通过索引的先后顺序保证数据可见性。而读索引和写索引各自只被一方修改另一方只读取天然避免竞争条件。我在答案里还补充了现代CPU乱序执行的问题指出需要用内存屏障保证写入数据在更新索引之前对消费者可见否则可能出现消费者拿到新索引但读到的还是旧数据的情况。这道题能答完整基本就能拿到不错的印象分。4. 算法与编程题实战两道题背后的工程思维4.1 编程题一单链表反转递归和非递归的细节编程题第一道是“实现单链表反转分别使用迭代和递归两种方式”。这道题在LeetCode上是第206题看起来简单但真正考察的是对链表结构的理解深度以及能不能在紧张环境下保持代码干净。迭代方式的核心逻辑是三个指针prev指向当前节点的前一个节点curr指向当前节点next临时保存当前节点的下一个节点。每轮循环做三件事先保存next再把curr的next指针指向前一个节点prev最后把prev和curr都向后移动一位。循环结束条件是curr为空此时prev正好指向新的头节点。struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; ListNode* reverseListIterative(ListNode* head) { ListNode* prev nullptr; ListNode* curr head; while (curr ! nullptr) { ListNode* next curr-next; curr-next prev; prev curr; curr next; } return prev; }递归的方式稍微抽象一点。核心思路是先反转当前节点后面的链表然后把当前节点的下一个节点的next指向当前节点最后当前节点的next置空。关键在于递归的终止条件是链表为空或者只有一个节点。ListNode* reverseListRecursive(ListNode* head) { if (head nullptr || head-next nullptr) { return head; } ListNode* newHead reverseListRecursive(head-next); head-next-next head; head-next nullptr; return newHead; }很多人递归版本写不对就是没有理解head-next-next head这一步的含义。这句话其实是说当前节点的下一个节点它的后继应该反过来指向当前节点。可以想象成两个人手拉手站着你要让后面那个人转过身来牵住你。我在答题时额外注释了两种方式的时空复杂度迭代法是O(n)时间O(1)空间递归法是O(n)时间O(n)空间因为递归需要调用栈。还特意提到在嵌入式开发中如果链表很长递归可能导致栈溢出所以工程上优先选迭代。这种细节能体现出你有工程考量而不是只会解LeetCode。4.2 编程题二字符串分割与拼接的边界条件第二道编程题是“给定一个字符串和一个分隔符将字符串按分隔符拆分并输出逆序拼接结果”。乍一看很简单但实际写起来有很多边界条件需要处理字符串为空、分隔符在开头或结尾连续出现、分隔符本身是多个字符、字符串中不存在分隔符。这道题的时间有限我用了最直接的方案用一个索引index遍历字符串用find函数查找下一个分隔符的位置截取两个分隔符之间的子串存入vector最后逆序遍历拼接输出。这种解法的好处是代码直观、不容易出错面试场景下优先保证正确性再考虑优化。不过我知道这道题真正想考察的其实是“你会不会处理空字符串”。如果原始字符串是“a,,b,,c”按逗号分隔很多人的第一反应是直接split得到“a”“”“b”“”“c”五个部分但实际需求可能是忽略空的部分。不同编程语言和不同库的split实现行为不一样C标准库本身没有split函数需要自己实现这就更能看出工程经验的差异。我当时在答题纸上专门用一个段落列出了各种边界情况并说明自己的处理策略连续分隔符产生的空子串可以选择跳过或保留取决于业务需求但在通用工具函数里建议保留由调用方决定是否过滤。这种考虑在工业软件开发中非常常见因为设备上报的数据经常出现空字段或异常格式一个健壮的解析函数能省很多排查问题的精力。4.3 笔试编程题通用的四个提效技巧编程题这一Part我总结几个通用经验能帮你提高笔试通过率。第一先写解题思路再编码。哪怕是基础题也要在代码前用一到两句话说明思路比如“使用双指针遍历链表一次遍历完成反转”。这既是给阅卷人看也是帮自己理清逻辑。第二边界条件单独处理。链表为空、只有一个节点、字符串为空、分隔符在开头、两个分隔符连在一起所有你能想到的异常情况都要有对应的代码分支或者至少用明确的注释说明你的处理方式。第三命名规范要到位。变量名用prev、curr、next、index、token这种“见名知意”的命名不要写p1、p2、tmp阅卷体验好很多。代码风格在笔试中占的印象分比很多人想象的更重要。第四答完留1到2分钟检查。重点检查变量是否初始化、循环是否可能死循环、递归是否有终止条件、是否有内存泄漏风险。C/C笔试中内存泄漏和悬空指针是扣分重灾区。5. 常见问题与避坑指南我把踩过的坑都写在这里5.1 笔试过程中的三个“十分钟陷阱”第一坑在选择题上纠结太久。东土科技的选择题里有很多“模棱两可”的干扰项尤其是C语言指针和操作系统进程状态相关的题目你越看越觉得每个选项都有道理。我的建议是一道选择题超过90秒还没确定答案先标记跳过最后有时间再回来看。笔试时间120分钟看着充裕但后面编程题和简答题都很耗时前面的犹豫会挤压后面的思考空间。第二坑简答题只写关键词不展开。笔试不是面试阅卷人只能通过文字判断你的水平。你写“使用互斥锁保护共享资源”跟写“使用互斥锁保护共享资源选择互斥锁而非自旋锁是因为临界区可能发生线程阻塞此时自旋锁会持续占用CPU导致忙等待”给阅卷人的感觉完全不在一个层级。笔试里一定把每个观点后面的“为什么”写出来。第三坑编程题先追求一次通过而不做本地测试。笔试系统通常不提供编译运行环境你要在纯文本里写代码这时候更要“人脑运行一遍”代码逻辑。我的习惯是代码写完后手动用一个简单用例逐行走一遍比如反转链表用1-2-3-4走一遍看一下每次循环结束后prev、curr、next三个指针分别指向哪里。这招虽然原始但能拦截掉80%以上的低级错误。5.2 知识点复盘这些考点值得你重点准备结合我这次笔试和之前准备嵌入式软件开发面试题的经验下面这张表里整理的是东土科技这类工业软件公司软件开发岗最常考的知识点备考时可以按优先级排序。优先级考点模块高频子知识点我的建议P0C语言/指针指针运算、内存分配与释放、函数指针手写至少20道指针相关代码题P0数据结构链表、栈、队列、二叉树基础掌握《剑指Offer》前50题P0操作系统进程线程、内存管理、进程间通信结合Linux项目实操去理解不止背概念P1计算机网络TCP/UDP、IP协议、Socket编程重点理解协议格式和状态机P1嵌入式/实时中断、RTOS任务调度、无锁队列有开发板就做个小型实践项目P2CRAII、智能指针、STL容器能讲清楚底层原理即可P2算法排序、双指针、动态规划LeetCode简单中等题刷100道左右我个人认为P0级别的知识点是笔试能否拿高分的分水岭尤其是内存管理和指针这两块几乎每道题都在变着花样考。而P1级别的知识靠梳理题目主动去补课会更高效P2级别只要不拖后腿就行不会决定offer的归属。5.3 时间分配与答题顺序我的“三阶段策略”我这次笔试的时间分配是选择题和判断题40分钟、简答题30分钟、编程题40分钟、最后留10分钟检查。这是个保守但有效的策略核心原则是“先把该拿的分拿满再挑战高难度题目”。第一阶段快速扫一遍所有题目。拿到试卷后先用3到5分钟把题目全部看一遍标记出哪些是“必拿分”的基础题、哪些是“需要思考”的中等题、哪些是“可能做不完”的难题。这样心里有数不会在中途发现后面有简单的大题但时间已经不够了。第二阶段从头开始按顺序答题但遇到纠结的选择题先跳过。笔试系统的进度条会真实反映你的答题进度如果前面跳过了太多题中后期会焦虑反而影响状态。所以我的策略是只跳过特别不确定的题其他题目一次性给出答案。第三阶段编程题放在简答题之后做。如果你的编程基础一般先做简答题的性价比更高因为简答题只要写了就有过程分而编程题如果思路不完整可能零分。我当时先把两道编程题的思路和关键代码框架写在草稿纸上再逐句完善代码这样即使时间不够阅卷人也能看到完整的解题思路。5.4 关于公司背景为什么东土科技会出这些题最后说一点备考心态上的建议。秋招笔试不只是一个被筛选的过程更是你判断公司是否适合自己的窗口。从东土科技的笔试题量分布来看它的软件开发岗对底层原理的重视程度明显高于对业务开发的重视程度这也跟它做工业互联网和嵌入式产品的定位一致。如果你对Linux内核、通信协议栈、实时操作系统这些话题本身就感兴趣那东土的笔试准备过程会非常充实因为每道题都能在真实工程中找到对应场景。如果发现自己对这些内容完全提不起兴趣那笔试的结果可能反而是个提醒也许你更适合走应用层开发方向。我当时在备考阶段对实时操作系统和共享内存通信并不特别熟悉于是在笔试前集中补了嵌入式软件开发面试题的高频考点还专门找了一块开发板把中断、定时器、任务调度的代码实际跑了一遍。笔试时遇到相关题目我能从实际现象反推原理手感和状态都好了很多。最后再分享一个小技巧笔试前一周不要盲目刷难题把精力放在C语言指针、内存管理和链表操作这些高频基础题上并且每天保持手写代码的手感。笔试当天提前用熟悉的环境敲一遍链表反转、字符串分割、快排这三个经典代码相当于给大脑做了热身进考场之后思路会顺很多。
返回列表