
百度2023校招C /PHP研发工程师笔试卷第一批这份卷子在我朋友圈里刷屏过一阵。投了百度C 开发、PHP开发岗的同学基本都做过同一套题网上讨论帖也特别多。我专门把这份卷子翻出来完整做了一遍又对照牛客、知乎各路经验帖复盘了一圈今天干脆把整套卷子的考点逻辑、题目类型、以及备考时最容易踩的坑一次说清楚。这份卷子适合谁看两类人一类是正在准备大厂校招、尤其是瞄准百度或同级别互联网公司研发岗的应届生另一类是已经工作几年、想回头补一补计算机基础底子的在职工程师。无论你是C 方向还是PHP方向这套卷子的考察思路都值得认真琢磨一遍——它某种程度上就是一个大厂对“合格研发工程师”的最低定义。1. 卷面总览百度技术笔试到底在筛什么人先看整体结构。百度这套2023校招C /PHP笔试卷第一批从题型上大致可以分为四块基础知识选择题、代码输出题、简答题、编程题。其中选择题覆盖范围很杂从操作系统、网络、数据库到语言特性都有涉及代码输出题在C 卷里占比很高通常给你一段短代码让你写出运行结果这是非常经典的“基础不牢就露馅”的题型简答题主要考概念理解和场景设计比如“如何设计一个短链接系统”“PHP-FPM的进程模型是怎样的”这类问题最后的编程题一般是两道左右第一道偏基础算法第二道偏工程或字符串处理。从考点分布来看我做了个粗略统计考察方向常见题型占比估算难度定位C/C语言特性选择题、输出题约35%中低但陷阱多PHP语言特性选择题、简答约25%中低数据结构与算法编程题约20%中高操作系统/网络/数据库选择题、简答约15%中场景设计与工程实践简答、开放题约5%中高这个结构说明一件事百度笔试的筛选逻辑不是“考倒你”而是“看你哪里会露馅”。它不追求题目本身多难而是通过覆盖足够广的基础面快速识别哪些候选人是真正系统学过、哪些只是刷了几百道LeetCode题。所以很多人出来说“感觉题目不难但就是拿不准”这恰恰说明卷子设计得很成功。1.1 题型结构背后的筛选逻辑我在复盘这份卷子时最大的感受是它的题目设计和百度实际的业务技术栈高度相关。C 方向明显偏向系统级、基础设施类岗位的候选人画像。百度有大量自研的底层组件、存储系统、服务治理框架这些系统对内存管理、并发控制、性能调优的要求极高所以笔试里C 相关的题特别爱考内存布局、指针运算、构造函数析构顺序这些细节。哪怕是选择题也经常让你比较几种写法的性能差异这属于典型的高性能服务端开发思维。PHP方向则对应百度生态里偏业务侧、Web服务侧的岗位。百度的搜索服务、贴吧、网盘等业务有大量PHP遗留系统以及基于PHP构建的Web中间层。这类岗位对候选人的要求是语言基础扎实、能写出安全的Web代码、对常见框架和性能优化有概念。所以PHP方向的题会更倾向于考察数组函数、变量作用域、PDO使用、常见安全问题这些贴近实际业务的东西。理解了这一层逻辑你就明白了这不是一份可以靠考前突击“模板题”搞定的卷子它考察的是你过去几年学习/工作时积累的底层基座。所以我建议所有备考者别急着上来就刷题先把考察逻辑盘清楚。1.2 卷面难度分布为什么感觉“不难但分不高”另一个值得聊的现象是很多考生考完出来觉得题目不算难但实际分数并不理想。我复盘后发现原因有三。第一选择题的陷阱设计得很隐蔽。比如C 里“int const *p”和“int * const p”的区别这种题你在牛客上刷过一百遍但试卷上它会换一个更复杂的组合比如“const int * const p”或者结合typedef函数指针一起考一个选项里藏两个坑一不留神就选错。第二PHP选择题会考不少“为什么是错的”而不是“什么是正确的”。比如它会给你一段在旧版本PHP里能运行、在新版本里会报Warning的代码问你问题出在哪。这种题目要求你对版本差异和语言演进有了解而大部分应试者只背结论不追原因所以很容易折在这里。第三代码输出题对“精确性”要求极高。输出题通常要求写清楚每一个字符包括空格、换行、类型。不少人能算个大概但输出格式写不完整同样扣分。考官在这个过程中筛掉的不是“不够聪明的人”而是“不够严谨的人”。2. C/C方向考点拆解从基础语法到系统编程陷阱C/C是这份卷子的大头也是很多人的“噩梦区”。我拆开来讲重点说说那些高频考法和它们背后的原理。2.1 指针与内存笔试拉开差距的分水岭指针相关题目在C/C方向几乎是必考的而且占比不小。常见考法有三种指针运算、指针与数组的关系、指针与函数参数传递。指针运算是最经典的之前热词里就反复出现“字符串逆序输出c”这就是典型的指针操作题。一份常见的考法是给你下面这样的代码让你写出输出结果#include stdio.h int main() { char str[] hello; char *p str; printf(%c\n, *(p 2)); printf(%c\n, p[2]); return 0; }这个不难答案都是l。但如果题目把char str[]改成char *str hello性质就变了——前者是栈上数组内容可修改后者是字符串常量存放在只读数据段写入会引发运行时错误。这个考点几乎每年都会出现因为它考察的是对“内存布局”的理解而非单纯语法记忆。另一个高频陷阱是“指针步长”。比如int arr[4] {1, 2, 3, 4}; int *p arr; printf(%p\n, p); printf(%p\n, p 1);有些同学会觉得p加1就是地址值加1其实在int类型的指针上p1会跨过4个字节。这种“步长由类型决定”的特性在笔试里会被反复印证尤其是当指针类型是结构体、自定义类时偏移量计算很容易出错。指针与函数参数传递这块通常会结合“交换两个数”的经典代码考。因为C语言里函数传参是值传递所以想通过函数修改外部变量必须传指针而C里则多了引用传递这个选项。很多卷子会让你判断几段代码中哪些能真正交换两个变量的值哪些只是“貌似交换了”考察的就是对实参形参关系的理解。内存分配这块会考malloc/free配对使用、new/delete配对使用以及对堆和栈差异的辨析。我记得有一套题专门问“为什么栈上分配比堆上分配快”这背后涉及操作系统虚拟内存管理、页表、缺页中断等知识。如果你理解栈是线程私有、连续、硬件级别的SP寄存器直接移动来分配而堆需要维护空闲链表、加锁和系统调用扩展就不会答错。2.2 字符串处理与文件读写基本盘不能丢字符串是C/C笔试里最“亲民”也是最爱挖坑的知识点。原因很简单字符串操作直接涉及指针、数组、内存边界是检验C语言功底的试金石。除了上面提到的字符串逆序“strlen与sizeof的区别”也是必考内容。很多人背了结论“sizeof是运算符strlen是函数”但遇到实际代码还是会错。比如char str[] hello; printf(%zu\n, sizeof(str)); // 输出6包括结尾的\0 printf(%zu\n, strlen(str)); // 输出5而如果改成函数参数呢void func(char arr[]) { printf(%zu\n, sizeof(arr)); // 退化成指针64位系统输出8 }数组作为函数参数时退化为指针sizeof得到的是指针大小这个特性在笔试里几乎每年出现一次。背后的原因是出于效率考量C语言在参数传递时无法也不愿复制整个数组只能传首地址。理解了这一点就不会再记混。文件读写这块热词里有“c语言文件读写操作代码”说明这也是搜索热门知识点。笔试卷里对文件读写的考察通常不复杂主要集中在fopen的打开模式选择、fread/fwrite和fgets/fputs的区别、feof的使用陷阱。我特别提醒一下feof这个函数。很多新手会这样写while (!feof(fp)) { fgets(buf, sizeof(buf), fp); // 处理buf }表面看逻辑没问题实际上feof只有在尝试读取越过文件末尾后才会被触发所以最后一次循环中fgets已经读取失败buf是未定义内容你还对buf做了处理。正确做法应该是优先判断fgets的返回值而不是判断feof。这种细节题在笔试卷里有一个特点它不会直接考你“知道不知道”而是给你一段代码问“哪里有问题”如果你自己写过类似代码一眼就看穿如果只是背书就很容易被带进沟里。2.3 类与对象C方向的区分度题目C方向的题除了基础语法最常考的就是类相关的生命周期和构造析构顺序。构造函数与析构函数的调用顺序是经典题。比如class A { public: A() { cout A; } ~A() { cout ~A; } }; class B : public A { public: B() { cout B; } ~B() { cout ~B; } };然后问“创建B对象时输出什么”。基础版答案是构造输出AB析构输出~B~A。构造顺序是先基类后派生类析构顺序是先派生类后基类这是为了保证派生类可以安全使用基类成员。但笔试很少只考这个基础版它还会加一个成员变量的维度class A { public: A() { cout A; } ~A() { cout ~A; } }; class B { public: B() { cout B; } }; class C : public A { private: B b; public: C() { cout C; } ~C() { cout ~C; } };构造顺序是基类A先构造然后按声明顺序构造成员对象b最后执行C的构造函数体。所以输出是ABC。成员对象的声明顺序影响构造顺序而不是初始化列表的书写顺序这个知识点辨析度很高卷子很喜欢拿来出题。虚函数和多态也是常客。笔试一般会考虚函数表的存在意义、纯虚函数与抽象类、以及在构造函数中调用虚函数会发生什么。最后一个点是重灾区构造函数中调用虚函数不会触发动态绑定因为构造期间对象的动态类型被绑定为当前正在构造的类。很多人不理解这一点被问到时很懵。我建议备考的同学把这部分往深里看一层不要只停留在“虚函数支持多态”这个层面要把虚函数表指针vptr、虚函数表vtable的布局和继承关系大致了解清楚。不是因为笔试会直接问你vptr存储在对象内存的哪个位置而是理解了这些底层机制选择题里的很多“歪门邪道”你一眼就能看穿。3. PHP方向考点拆解不仅写代码更要会防御PHP方向的题目和C/C方向气质完全不同它更贴近Web业务开发日常。我的整体感受是它要求你不仅会写PHP代码还要知道怎么写才是安全的、高效的、可维护的。3.1 PHP基础特性变量作用域与数组操作PHP的基础选择题主要集中在变量作用域、超全局变量、数组函数这几个点。变量作用域是面试官特别爱考的一个点。比如在函数内部访问全局变量需要显式用global关键字或通过$GLOBALS超全局数组访问。代码如下$name zhangsan; function test() { echo $name; // 报错未定义变量 global $name; echo $name; // 输出 zhangsan echo $GLOBALS[name]; // 输出 zhangsan }这个细节本身就是很多PHP开发者实际写代码时踩过的坑。笔试考它目的是筛选出那些真正写过PHP、而不是只在简历上写“熟悉PHP”的候选人。数组函数也是重头戏。PHP数组是一个“有序映射”这个特性让它比C/C里的数组灵活得多但同时也带来了一些“反直觉”行为。笔试中常考的有array_merge与数组相加的区别、array_map与array_walk的区别、foreach遍历数组时修改元素的方式、sort系函数与asort系函数的区别——前者会重置键名后者会保留键值关联。有一个题我记得特别清楚$a [1, 2, 3]; $b [4, 5, 6]; $result $a $b;问$result的值是多少。答案是[1, 2, 3]因为数组相加会以第一个数组为主只在键名不存在于第一个数组时才合并进去。这个跟array_merge数字索引会重新编号、字符串键会覆盖的行为完全不同很多人没实际用过就直接猜答案十个里九个错。3.2 PHP中的错误处理机制从Notice到ExceptionPHP的错误处理机制理解深度能直接看出一个人是“写业务码”还是“系统学过的开发者”。PHP里的错误分为好几层Notice、Warning、Fatal Error还有PHP 5.3之后引入的Exception、PHP 7之后引入的Error和Throwable。笔试常考的点是什么时候用try/catch什么时候用错误处理器什么时候又会直接Fatal。一个高频考点是类型声明不匹配时PHP会抛出什么在PHP 7之前可能只是一个可恢复错误在PHP 7之后如果开启严格类型模式会抛出TypeError。而TypeError是Error的子类Error实现Throwable接口但它和Exception是并列关系不是继承关系。所以如果你用catch (Exception $e)是接不住TypeError的必须用catch (Throwable $e)才能捕获所有异常和错误。这个知识点非常细但笔试一旦出现就很挑人。我在实际业务开发中也遇到过类似的坑。早期PHP代码里连接数据库失败只是产生Warning脚本继续往下走然后所有查询全失败最后才暴露一堆奇奇怪怪的问题。后来改成使用PDO的异常模式在构造PDO对象时设置ATTR_ERRMODE ERRMODE_EXCEPTION数据库层面的问题才会第一时间以异常形式抛出来再统一交给全局异常处理器处理。这个经验放在笔试简答题里也很容易拿分。3.3 PHP安全问题SQL注入、文件上传与反序列化百度作为搜索引擎起家对Web安全的重视程度很高。PHP方向的笔试通常不会考很复杂的渗透技巧但一定会考基础的Web安全常识。SQL注入是必考题而且往往不是直接问“什么是SQL注入”而是给你一段代码问哪里有问题$id $_GET[id]; $sql SELECT * FROM users WHERE id $id; $result mysqli_query($conn, $sql);正确答案是$id直接拼接进SQL语句存在注入风险。但笔试还想让你写出修复方案那就要说清楚使用PDO预处理或mysqli的绑定参数功能核心原理是SQL语句结构在绑定参数之前已经被数据库解析完成用户输入只能作为参数值传递无法改变语句结构。文件上传漏洞也是高频点。一个经典题目是让你看下面这段代码有什么问题if ($_FILES[file][type] image/jpeg) { // 保存文件 }外行人会觉得检查了MIME类型就安全了实际上$_FILES[file][type]完全由客户端可控用Burp Suite之类的工具改一个请求头就能绕过。正确做法应该是在服务端通过getimagesize()或finfo_file()读取文件真实内容类型来判断甚至更进一步将上传目录设置为不可执行脚本、对文件进行重命名、限制文件大小等。反序列化漏洞在近年笔试中的出现频率也越来越高。PHP的serialize/unserialize机制本身没有安全风险但如果你在反序列化用户可控的数据同时代码中存在魔术方法如__destruct、__wakeup和可利用的POP链就可能导致任意代码执行或文件操作。CTF比赛中有不少以PHP反序列化为核心的题热词里也有“[极客大挑战 2019]php”这类搜索关键词说明已经有很多参赛者在准备这类知识。3.4 PHP框架与工程化从ThinkPHP到现代化开发PHP方向的简答题偶尔会涉及框架内容尤其是ThinkPHP这种国内使用广泛的经典框架。热词里出现了“thinkphp3.2.3”说明还是有不少人在搜索相关教程。不过我要提醒一句笔试考框架大概率不是考你某个版本的具体用法而是考你对框架核心机制的理解。框架层面的高频考点有三个。第一是MVC架构的思想。为什么要分层因为控制器负责接收请求、调度模型和视图模型负责业务逻辑和数据访问视图负责展示。分层之后代码的复用性和可维护性大幅提升。第二是依赖注入和控制反转。在传统写法中类内部自己new依赖对象在依赖注入写法中依赖由外部传入。这样做的最大好处是方便测试——你可以传一个mock对象进去而不需要真正初始化数据库连接。第三是Composer自动加载机制。Composer的自动加载原理其实不大复杂维护一个类名到文件路径的映射表或者在命名空间规律的指导下通过PSR-4标准推断路径只有当类被使用时才加载对应文件即懒加载。理解了这套机制不仅能解答笔试题目实际开发中遇到“类找不到”“autoload失败”也可以更快定位问题。另外PHP-FPM的进程模型也是一个经典简答题。比如“PHP-FPM的两种进程管理模式Static和Dynamic的区别”Static模式固定worker进程数适合高并发稳定负载场景Dynamic模式根据min/max配置动态调整进程数适合负载波动较大的场景。这属于工程实践层面的知识有实际运维经验的人才能答得比较到位。4. 编程题与手写代码真题类型的解题思路编程题是这份试卷的拉分项。C/C方向和PHP方向的编程题会有些不同但整体上不会跳出字符串处理、数组操作、基础算法这三个大类。4.1 字符串处理类从逆序到去重的不同写法“字符串逆序输出”是经典中的经典既会出现在C 选择填空里也会作为编程大题出现。我来梳理一下C语言的几种典型解法#include stdio.h #include string.h void reverse(char *str) { int left 0; int right strlen(str) - 1; while (left right) { char tmp str[left]; str[left] str[right]; str[right] tmp; left; right--; } } int main() { char str[] hello; reverse(str); printf(%s\n, str); return 0; }双指针法是最推荐的写法时间复杂度O(n)空间复杂度O(1)。有些同学会另开一个数组从后往前拷贝也能实现但多了一倍空间在笔试中不算最优解。再往前一步如果题目变成“逆序输出一句话但单词内部顺序不变”比如输入“hello world”输出“world hello”那就要先整体逆序再逐单词逆序。这种变体题考察的是举一反三能力在很多校招笔试中都有出现。PHP方向的字符串题则常常是“写一个函数将字符串中的空格替换为%20”。这种题目在PHP里用str_replace一行就能搞定但如果出题人想考算法能力会限制你用正则或手写循环。其实现思路是先统计空格数再从后往前填充避免频繁移动大量字符。4.2 数据结构与算法笔试中的不变主线无论方向怎么分笔试里都会出现几道不抽象到具体语言、纯粹考算法思路的题目。常见的有链表反转、合并两个有序数组、二分查找、括号匹配、最长无重复子串等。链表反转在C语言里非常经典struct ListNode { int val; struct ListNode *next; }; struct ListNode *reverseList(struct ListNode *head) { struct ListNode *prev NULL; struct ListNode *curr head; while (curr) { struct ListNode *next curr-next; curr-next prev; prev curr; curr next; } return prev; }这种题的核心就是“记录下一个遍历位置”因为当你把当前节点的next指向前一个节点后如果不先保存next指针就会丢失整个链表剩下的部分。我见过很多同学在纸上画了链表结构但代码写出来仍然丢节点本质上是没有在脑子里模拟指针的移动过程。PHP方向的编程题则更偏向数组和哈希表。比如“找出数组中重复元素”可以用一个关联数组做哈希表统计这也是PHP最容易实现的方案function findDuplicate($arr) { $seen []; foreach ($arr as $val) { if (isset($seen[$val])) { return $val; } $seen[$val] true; } return -1; }时间复杂度O(n)空间复杂度O(n)。如果题目要求O(1)空间复杂度那就需要利用数组下标与数值之间的关系做标记法属于进阶思路了。4.3 笔试中的边界条件容易被忽略的得分点编程题真正拉分的其实不完全是算法本身而是边界条件处理。举个例子用C语言写字符串逆序时如果输入是空串你的reverse函数会怎样如果调用strlen为0那么right -1while循环不会进入所以不会出错。但如果输入是NULL呢strlen(NULL)会直接段错误。所以笔试编程题里起始就先判断入参是否为空指针这是一行保命代码。再比如二分查找的边界问题。low high会不会溢出在64位系统上int可能不会但在某些场景下会。更稳的写法是int mid low (high - low) / 2;避免直接加和导致溢出。这种细节卷子不一定会专门考但会体现在你去重时是否重复计算中间值、是否会造成死循环这些更具体的错误中。我建议笔试前准备一张“边界清单”空输入、单元素输入、输入已有序、输入完全逆序、输入有重复值、输入为大数值、输入为负数。每写完一段代码拿这几种情况分别模拟一遍。这个方法我在实际笔试中用过能有效减少“觉得自己写完了实际一堆漏洞”的情况。5. 备考策略与实操经验从刷题到进面的最后一公里最后这部分我想聊聊很多人关心的问题这份卷子到底该怎么准备有没有什么“捷径”我的答案可能跟主流不太一样少做模考卷多打基础。5.1 环境准备先搭好本地调试环境很多同学备考C/C方向时连本地编译环境都没配置好。热词里“vscode配置c/c环境”搜索量很高说明大家确实有需求。我建议花半小时配好环境安装VS Code、装好C/C扩展、配置好MinGWWindows或ClangmacOS/Linux再写个简单的Hello World验证。有一个来自实际经验的提醒如果在Windows上使用VS Code跑C/C经常会在配置launch.json和tasks.json时遇到路径问题。特别是编译器路径带空格或反斜杠转义不对容易报“无法打开终端”或“找不到任务”的错误。遇到这种情况优先检查tasks.json里的command和args路径用正斜杠替代反斜杠问题通常能解决。这个环境准备不仅是为了笔试更是为了你平时刷题练习。学C语言不自己跑代码等于白学调试器里看一遍栈帧和指针走向顶过你看十篇博客。5.2 刷题策略按专题推进而不是随机刷说回刷题。针对百度的风格我的建议是不要上来就随机刷LeetCode而是按专题逐个击破。首先是字符串专题包含逆序、查找子串、去重、字符统计。这是一部分基础。其次是链表专题包含反转、合并、删除倒数第N个节点、环形链表判断。链表题是最考验指针操作能力的刷完这一组你对“指针只是普通变量存的是地址”这句话的感受会完全不一样。然后是栈和队列专题括号匹配、最小栈、用队列实现栈。这个专题的题目套路固定练起来效率比较高。接着是排序和查找快排、归并、二分变种。大厂笔试中对排序算法本身的考察通常不再是手写快排而是在题目中隐含地考察你对复杂度、稳定性的理解。所以这一专题以原理理解为主。最后是动态规划和贪心爬楼梯、最大子数组和、零钱兑换。动态规划题在百度这类大厂的校招笔试里属于加分项不会特别难但如果其他题都做完做对了最后一道动态规划题就是拉开差距的关键。上述各专题都能找到大量对应题目。我建议每个专题至少做20道做好笔记把每道题的时间复杂度和空间复杂度写下来。笔试如果遇到类似题你可以快速判断用哪种方案。5.3 复盘方法论错了的题比对了的题更值钱笔试备考中我自己的一个很深的体会是刷题的量真的不重要重要的是你从每道错题里提炼出了什么。每次做完题我会把涉及的考点分类整理比如“这道题考的是指针步长我为什么在p1上搞错了”。过一段时间之后回头再看这些错题如果还是不能一眼看出答案说明这个知识点还没吃透需要再找同主题的题强化。PHP方向也一样。比如有一道题考“PDO预处理为什么能防止SQL注入”如果你只是记住了结论而没有搞清楚预处理的工作原理换一道问法你照样不会。但如果你理解了SQL语句的解析和执行是分两步的用户输入只在执行阶段作为参数绑定不会参与语句结构生成那么无论题目怎么变形你都能答对。我见过一些同学笔试完就丢了卷子错过的题第二次遇到还是错。这是最可惜的。5.4 从笔试到面试做对题只是第一步笔试通过只是第一关紧接着的面试会问得更深。百度的面试风格我个人的感受是比较注重“追根究底”你写的每一行代码、简历上的每一个项目都会被拆开问。比如笔试里考了指针和内存面试官就可能顺着问你指针数组和数组指针的区别是什么项目中哪里用过函数指针内存泄漏怎么排查如果你只是考前背了答案这一连串追问大概率会露馅。所以备考笔试时除了会做题还可以主动往深一层想这道题在真实工程中对应什么问题比如C 里vector扩容机制笔试可能会考均摊复杂度分析在工程中其实就是理解为什么频繁向vector头部插入元素性能很差PHP里isset与empty的区别实际编码时很多人会踩坑搞不清楚什么时候拿不准。带着工程视角去备考一通百通。写在最后回到这份卷子本身最后分享一点我个人的复盘感受。这份“百度2023校招C /PHP研发工程师笔试卷第一批”算不上特别难但它是一面很好的镜子照出了我在计算机基础上哪些地方是糊的、哪些地方是真正掌握的。我在实际备考中养成了一个习惯保持一个错题本。这里的错题不止是笔试中的错题还包括日常练手代码中遇到的奇奇怪怪的问题——比如C语言里数组退化、PHP里array_merge的字符串键覆盖行为——全部记录在案。考前翻一遍比临时刷几十道新题都管用。备考也好、工作也好技术这条路上真没有太多捷径。把基础打牢把每一道错题吃透笔试自然会给你一个合理的回报。