
每年秋招季一过总有一批“京东2019校招笔试C/C开发工程师笔试题”的旧题被翻出来反复讨论。原因很简单这套题基本代表了国内互联网大厂对C/C岗候选人的基础能力审美考察范围覆盖C语言语法细节、指针与内存、字符串处理、经典算法以及文件操作难度上比考研408略浅但比平时刷的LeetCode要“刁”得多。很多同学在校招群里对答案的时候才发现自己以为稳拿的选择题其实踩了一堆坑。这篇文章我按照当年笔试的实际考察节奏把这套题背后的知识点、常见陷阱和答题思路完整拆一遍顺便把很多事后复盘才想明白的细节也补上。如果你是准备大厂C/C岗的24届、25届学生或者正在系统复习C语言准备跳槽面试这篇文章能帮你少走很多弯路。1. 京东2019校招笔试题的总体风格与考察逻辑1.1 题目构成与难度分布这套笔试题的整体结构可以概括为“40道选择题 2道编程题”总分100分笔试时长90分钟。选择题占了70分左右编程题占30分。从知识面来分C语言基础语法和指针部分大约占了选择题的一半剩下的集中在数据结构、算法复杂度、操作系统基础和网络基础。编程题里一道偏字符串处理一道偏链表或数组操作都是让你手写完整函数不能调用外部库。我当年印象最深的是题目整体不偏但特别爱在“你以为你会的知识点”上埋坑。比如指针的指针、指针数组和数组指针的区别比如sizeof和strlen的纠缠比如while与do-while在边界条件下的行为差异。这些在课本上都学过但考场上容易因为“太熟”而掉进惯性思维的陷阱。从难度分布看基础送分题大概占20%中等题占60%真正的拉分题占20%。也就是说只要C语言基础扎实拿到70分不难但想进面试需要把那20%的拉分题也拿下这就得靠对底层原理的理解深度了。1.2 为什么大厂考试爱考基础题很多同学会疑惑都2025年了为什么校招笔试还在考C语言老八股其实大厂校招笔试的目的不是考你会不会某个框架而是筛选具备扎实计算基础的工程师。C语言作为最接近底层的语言之一能考察你对内存模型、指针操作、编译链接的理解这些能力决定了你以后能不能真正吃透更上层的技术。京东的技术栈里C/C主要用在交易系统的高性能模块、中间件、搜索和广告引擎等方向。这些场景对程序的性能和稳定性要求极高一个内存泄漏或野指针问题在线上可能会造成严重事故。笔试筛的就是对这些基础概念有直觉的人——你不需要背下所有细节但必须知道危险在哪里。另外还有一层现实原因校招简历量太大笔试需要一套标准化、成本低、机器可判分的筛选工具。客观选择题加手写算法的组合既能覆盖广又能量化排名。所以“京东2019校招笔试C/C开发工程师笔试题”这种风格至今仍是各大厂C/C岗笔试的主流范式。2. 核心考点拆解C语言基础与语法细节2.1 字符串处理笔试的“必考钉子户”字符串是C语言笔试最经典、最频繁的考点原因在于它完美结合了指针、数组和内存这三座大山。京东这套笔试里字符串逆序、字符串拷贝、求长度这类题目绝对跑不掉而且看起来越简单越容易失分。先看一道典型题实现字符串逆序函数void reverse(char* str)。很多同学第一反应是直接写void reverse(char* str) { int len strlen(str); for (int i 0; i len / 2; i) { char tmp str[i]; str[i] str[len - 1 - i]; str[len - 1 - i] tmp; } }这段代码本身没有错但它暴露了两个问题第一你调用了strlen如果面试官要求边界条件处理空指针直接崩溃第二如果题目要求不借助额外数组且只用O(1)空间这个写法没问题但如果你用的是下面这种指针式写法细节会更难。void reverse(char* str) { if (str NULL) return; char* end str; if (*end \0) return; while (*end) end; end--; while (str end) { char tmp *str; *str *end; *end-- tmp; } }两种写法都能过但考场上你必须想清楚题目是否允许修改原字符串是否要求处理空字符串是否考虑过char可能是有符号类型这些边界条件才是大厂笔试真正想看的点。另外字符串题目还特别喜欢和sizeof混在一起考。比如char str[] hello; printf(%zu %zu, sizeof(str), strlen(str));输出是6 5。因为sizeof在编译期就算出了整个数组的字节数包括结尾的\0而strlen是运行期数到\0就停。这道题本身不难但如果把str换成char* p hellosizeof(p)在64位系统上就是8而不是5或6。很多人栽在这里。2.2 控制流陷阱while与do-while的边界差异搜索热词里专门有一条“c语言while和do-while区别”说明这确实是高频考点。语法上大家都知道while先判断后执行do-while先执行后判断。但笔试不考这个它考的是“当条件不成立时哪个至少执行循环体一次”以及循环内部break和continue的相互作用。典型例子int i 0; do { i; } while (i 0); printf(%d, i); // 输出 1但如果把do-while换成while输出就是0。这个区别本身不难难的是和continue组合起来int i 0; do { i; if (i 2) continue; printf(i%d\n, i); } while (i 5);注意在do-while里continue会跳到条件判断处也就是while (i 5)而不是跳出整个循环。很多人写while习惯了以为continue一定跳到循环头部结果在do-while里把条件判断跳过了导致死循环或结果不对。还有一点do-while在宏定义里很常用比如#define DO_SOMETHING(x) do { ... } while(0)。这个技巧能够保证宏在if-else语句中作为一个完整语句被正确包裹不会出现悬空else的问题。这种“宏定义里的do-while”也是笔试选择题的常客你得能看懂它的意图。2.3 运算符优先级与类型转换的“送命题”C语言的运算符优先级表很长笔试不会让你背整个表但一定会挑几个最易错的组合来考。最常见的就是*p、(*p)、*p、*p这四个表达式的含义。*p先取*p的值然后指针p自增等价于*(p)(*p)取p指向的值然后这个值自增*p指针先自增再取新位置的*p*p取p指向的值然后让这个值自增这四个表达式后置自增和前置自增的顺序差异正是笔试的经典陷阱。如果你对运算符优先级不够敏感建议死记一个结论的优先级高于*但后置会返回自增前的值。稍微扩展一下p和p在同一个表达式里同时出现时C语言标准是未定义行为别再纠结谁先谁后。类型转换也是一个大类。int和unsigned int混在一起运算时会发生隐式转换结果是unsigned。比如int a -1; unsigned int b 1; if (a b) { printf(a b); } else { printf(a b); }输出是a b因为a会被转换成unsigned int变成0xFFFFFFFF当然大于1。这类题目在笔试里叫“隐性类型转换陷阱”不仅京东爱考几乎所有大厂都爱考。3. 指针、内存与底层原理拉开差距的关键3.1 指针运算与数组名的微妙关系指针部分向来是C/C笔试的分水岭。能拿下这部分的同学往往不是靠背诵而是真正理解了内存模型。京东这套笔试里指针相关题目占了不小比例。先说数组名。arr和arr在数值上相同但类型不同arr的类型是int*arr的类型是int (*)[5]指向整个数组。所以arr 1指向下一个元素而arr 1直接跳过整个数组。这个差异在选择题里经常以“输出是什么”的形式出现。int arr[5] {1, 2, 3, 4, 5}; int* p arr; printf(%d %d, *(p 1), *(arr 1)); // 2 2 printf(%d, (int)(arr 1 - arr)); // 整个数组的跨度 1但指针减法是按元素个数算的最后一行最容易错arr 1指向数组尾部之后减去arr等同于arr[0]按指针减法规则差值等于数组元素个数5而不是1。printf用%d输出(int)(arr 1 - arr)时是5。再看二维数组和指针数组。int* p[5]和int (*p)[5]的差别用一句话说int* p[5]是“5个指针组成的数组”int (*p)[5]是“指向5个int数组的指针”。阅读声明时用“右左法则”从标识符开始先向右看遇到]说明是数组遇到)再向左看遇到*说明是指针。3.2 内存管理考点谁分配谁释放C语言内存管理也是京东笔试的固定一环主要考察栈区、堆区、全局区、常量区、代码段的划分以及malloc/free的正确使用方式。选择题常见的错误选项包括free之后没有把指针置空导致野指针多次free同一块内存导致double freemalloc之后忘记检查返回值就直接解引用返回局部变量地址。这些错误被反复拿出来考因为线上C项目中这些错误会导致线上事故。栈区和堆区的区别也要能准确表达栈区由系统自动分配和释放函数调用时压栈返回时弹栈速度很快但空间有限堆区由程序员用malloc分配需要手动free空间更大但访问速度稍慢。全局变量存储在数据段BSS和初始化数据区常量字符串存储在只读的常量区尝试修改常量字符串会导致段错误。这里有个经典的坑char* func() { char str[] hello; return str; }这段代码返回了局部数组的首地址函数返回后栈帧被回收这个地址已经失效输出的内容是未定义的。很多同学写成char* str hello然后返回虽然也是错误代码但偶发情况下可能能正常输出因为字符串常量存储在静态区函数返回后内容还在。所以笔试特别喜欢把这两种写法放一起让你判断哪个是合法行为。3.3 文件读写笔试常客与字节流陷阱文件操作在笔试里考得不算深但每年都会出现。热词里“c语言文件读写操作代码”和“c语言文件”上榜说明大家在这块儿的掌握普遍偏弱。京东2019这套题的编程题里有一道和文件操作相关的题目要求从文件中读取若干整数计算平均值后写回另一个文件。看似简单但考察点很细文件打开模式是否正确r和rb的区别、文件是否成功打开、读取是否到了文件末尾、fscanf的返回值是否被忽略、整数溢出有没有考虑。一个规范的读整数文件写法FILE* fp fopen(input.txt, r); if (fp NULL) { perror(fopen); exit(EXIT_FAILURE); } int num, sum 0, count 0; while (fscanf(fp, %d, num) 1) { sum num; count; } fclose(fp);注意这里用fscanf的返回值来判断是否成功读取了一个整数而不是用feof。因为feof只有在读取越过文件末尾之后才会被置位在循环中直接用feof(fp)作为判断条件会导致多读一次或者在使用前没有检测错误。这是C程序设计经典误区也是笔试选择题的高频选项。4. 数据结构与算法从冒泡排序到最短路径4.1 排序算法你以为会了其实没会算法题在京东这套笔试中主要以“手写代码”的形式考。基础中的基础是排序尤其是冒泡排序。热词“冒泡排序c语言”说明这是大家搜索最多的算法之一。冒泡排序的代码本身很简单但笔试不会只让你写一个标准冒泡而是会加限制条件。比如“对链表进行冒泡排序”或“对数组用冒泡排序但只遍历一趟”。链表冒泡排序涉及到节点交换和指针调整比数组版复杂得多是常见的拉分题。void bubbleSortLinkedList(struct Node** head) { if (*head NULL || (*head)-next NULL) return; int swapped; struct Node* ptr; struct Node* last NULL; do { swapped 0; ptr *head; while (ptr-next ! last) { if (ptr-data ptr-next-data) { swap(ptr-data, ptr-next-data); swapped 1; } ptr ptr-next; } last ptr; } while (swapped); }这里交换的是节点数据而不是交换指针在笔试中一般都可以接受但如果面试官进一步追问“如何通过交换节点本身来实现”你需要知道需要维护前驱节点边界处理会复杂很多。另外笔试也很喜欢考“快速排序的最坏时间复杂度是O(n^2)但平均是O(n log n)”这类概念同时询问排序是否稳定。冒泡、插入、归并是稳定的快排、堆排、选择排序不稳定。京东这套题的选择题里有一道就是让判断“下列说法错误的是”四个选项分别涉及堆排序空间复杂度、快排最坏情况、归并排序稳定性、计数排序适用范围覆盖非常全面。4.2 迪杰斯特拉算法与图的存储方式热词“迪杰斯特拉c”暴露了这套笔试里有一道和最短路径相关的题。迪杰斯特拉算法Dijkstra是图论中单源最短路径的经典算法思路是贪心每次选当前距离最小的未访问顶点然后松弛其邻接边。笔试通常不会只让你默写算法而是先给一张图让你写出从源点到各点的最短路径数组。这里考的是你是否清楚算法流程以及松弛操作的具体执行顺序。如果写成代码优先队列优化版堆优化和朴素版都要能搞定。朴素版时间复杂度O(V^2)堆优化版O((VE) log V)。图的存储方式也是考点。邻接矩阵和邻接表的适用范围要分清楚稠密图用邻接矩阵简单直观稀疏图用邻接表节省空间。如果边权有负数迪杰斯特拉算法就不适用了得换Bellman-Ford或SPFA。这道题经常以附加问的形式出现目的考察你有没有理解算法的适用边界。4.3 时间复杂度与空间复杂度的计算套路笔试选择题中至少有两三道纯粹考复杂度。比如一个嵌套循环for (int i 1; i n; i * 2) { for (int j 1; j n; j) { // O(1) } }外层循环执行log n次内层执行n次总复杂度是O(n log n)。很多人会把外层写成O(n)忽略了变量翻倍的增长规律。另一个常见考法是对递归函数求复杂度比如二分查找是O(log n)归并排序是O(n log n)斐波那契数列的朴素递归是O(2^n)。除了时间复杂度空间复杂度也要会算。递归深度是多少额外开了几个数组是否原地排序这些都要在注释里体现出来。很多编程题要求“空间复杂度O(1)或O(log n)”如果不满足即使功能正确也会扣分。5. 实操现场模拟一套答题思路还原5.1 选择题的快速排除法考场上90分钟要做完40道选择和2道编程题时间很紧。正确的策略是先快速浏览一遍选择题把一眼能确定答案的题目做完大约需要15分钟把不确定的标记下来第二遍再专心思考不要在一道题上纠结超过3分钟。C语言笔试的选择题有很强的“套路性”选项里如果出现“未定义行为”“编译错误”“运行崩溃”这类说法往往就是正确答案所在。比如问printf(%d, printf(abc));的输出答案是abc3因为内层printf返回3。很多人不了解printf的返回值直接懵掉。再比如选项中出现“数组越界”和“字符串结尾没有\0”这类描述通常是对的核心。做选择题时还有一种技巧把代码中的变量替换成具体数字在草稿纸上一步步模拟运行。不要试图在脑子里空想尤其是数组下标和指针偏移的问题画出来比什么都管用。5.2 编程题的答题步骤与代码规范京东这套笔试的编程题必须在网页编辑器里手写代码不能补全不能运行调试。所以在提交之前一定要“人肉编译”一遍检查每个变量是否声明每对花括号是否匹配有没有少写分号边界条件是还是。我推荐的编程题答题流程是先审题明确输入输出格式和时间空间限制再设计数据结构不要一上来就写代码然后用3到5个简单用例在草稿纸上验证思路包括空输入、单元素、最大值、最小值等边界情况最后再动手写代码写完逐行读一遍检查错误。代码风格也会影响评分因为大部分批改系统会做“部分得分”判定。即使整体功能没写完如果关键步骤的注释写清楚了或者核心逻辑对了会拿到部分分数。所以建议在代码开头用注释概括思路比如// 思路双指针从两端向中间扫描交换字符 // 边界条件空串、单字符、指针相遇时停止5.3 常见失分点与排查技巧实录这里整理一下历届学生在这套笔试题上最容易丢分的几个点也是我当年踩过的坑。第一个是sizeof和strlen混用。做数组长度题时分清楚是数组名还是指针。数组是编译期定长指针在64位系统上恒为8字节这个一定要写进错题本。第二个是字符串数组的初始化。char* s abc和char s[] abc看起来差不多但前者是常量不能修改后者是栈上拷贝可以修改。笔试选择题经常给出“哪个可能段错误”之类的提问选char* s abc; s[0] x;不会错。第三个是malloc之后没有检查返回值。很多同学在平时练习时因为内存充足从不检查malloc是否成功但在笔试的填空判断题里这属于“必要步骤缺失”容易被扣分。凡是考到内存分配答题时一定要加上对NULL的判断。第四个是文件操作相关。笔试中文件题不多但只要考到打开失败的处理基本必考。有些同学的代码里全是fopen但没有if (fp NULL)直接导致程序在目标机器上崩溃批改系统判0分。5.4 笔试题的实战代码示例解析这里我用一道典型的京东风编程题做示例题目是给定一个字符串将其中的每个单词反转单词之间用空格分隔保持单词顺序不变。例如输入hello world输出olleh dlrow。思路分两步第一步将整个字符串反转得到dlrow olleh第二步遍历字符串对每个空格分隔的单词再次反转实现单词内字符顺序复原且整体顺序不变。#include stdio.h #include string.h void reverse(char* start, char* end) { while (start end) { char tmp *start; *start *end; *end-- tmp; } } void reverseWords(char* s) { if (s NULL) return; int len strlen(s); // 第一步反转整个字符串 reverse(s, s len - 1); // 第二步逐个单词反转 char* start s; char* pos s; while (*pos) { if (*pos ) { reverse(start, pos - 1); pos; start pos; } else { pos; } } // 处理最后一个单词 reverse(start, pos - 1); }要注意的是如果原字符串有多个连续空格这个代码会失效或反转空片段需要加一个判断只有start pos - 1时才执行reverse。另外如果题目要求不修改原字符串就不能用这个原地处理函数需要额外分配空间。这类“题目看起来简单边界条件一环扣一环”的题目正是京东校招笔试的特点。6. 备考建议与面试官视角的评分逻辑6.1 不同基础水平的备考路径如果你是基础薄弱的同学我的建议是不要直接刷LeetCode先把C语言课本上的指针、数组、字符串、结构体、文件操作这几章彻底吃透尤其是课后习题要全部手写一遍。不要盯着屏幕看一定要在纸上或者在本地环境里跑。京东这套笔试题的很多知识点都是从教材习题变形来的。如果你已经有了一定基础直接刷历年真题和经典笔试题库重点练选择题。特别是“求输出结果”类题目做完之后一定要追问自己为什么是这个结果如果我改了某个类型结果会变吗这个过程能帮你建立编译期的“肌肉记忆”。如果你是准备冲刺大厂的同学建议把C语言和C的区别也理一遍C语言没有重载、没有类和模板、没有STL笔试虽然以C为主但C岗常会在考察后缀加几个C语法题。京东笔试官方明确是C/C开发一般两种代码都可以写你要挑自己最熟的语言。6.2 笔试后的复盘清单考完笔试出来第一时间记下还能回忆起来的题目不要等第二天。我当时考完就立刻在备忘录里整理了20多道还原题晚上按知识点分类把错题对应的章节重新过了一遍。这个习惯让我后续几家公司的笔试明显顺手了很多。复盘时至少要回答这几个问题哪些题是蒙对的哪些题是真正掌握的哪些题完全没思路没思路的题目涉及哪个知识模块是自己没学还是学了没复习到编程题在边界条件上有没有踩坑代码风格是否需要改进。把这些答案汇总成一张表比盲目刷题高效得多。另外要提醒一句京东笔试是双机位监控不允许编译调试提交后无法再看自己的代码。所以平时一定要养成“一次写对”的习惯尽量少依赖编译器来提醒自己有没有漏分号。我建议在笔试前一周每天用白纸手写一到两个C语言函数写完再敲进 IDE 验证这个练习非常有效。7. 写在最后一点个人体会校招笔试这件事说到底就是一场“基础能力的极限测试”。京东2019校招笔试C/C开发工程师这套题之所以到现在还有人翻出来复习就是因为它考察的知识点足够经典、陷阱足够真实能准确反映一个候选人有没有在C语言上花过功夫。我见过项目经历非常丰富但笔试挂掉的同学也见过只会啃课本却顺利通关的同学差距往往不在智商而在基础是否扎实。我个人的体会是拿到一套校招笔试真题不要只追求把答案写对要把每一道题背后的考点都挖出来整理成属于自己的知识地图。C语言的知识点之间是有依赖关系的指针不通链表和树就写不顺内存不理解文件操作和字符串处理就容易踩坑。希望这篇拆解能帮你对这套经典笔试题建立起整体认知也祝正在准备校招的你在笔试环节少丢分、多拿分。