数组越界这个坑,我面试的时候也栽过 前几天有个读者给我发了段代码说面试的时候写的让我帮忙看看哪里有问题。int sensor_data[100]; for (int i 0; i 100; i) { sensor_data[i] readSensor(); }我一看就笑了——哦不是心疼。i 100数组越界了。他问我老师这种低级错误是不是特别减分我说减分是肯定的但没那么致命。致命的是你写完之后没有检查。讲真数组越界这种问题不只是新手会犯。我面过工作五年的人照样在这种地方翻车。不是不会是写代码的时候没那个意识。C风格数组 vs std::vector选哪个先说个基础问题C里数组有两种写法C风格的int arr[100]和STL的std::vectorint。面试的时候如果你说我用C数组面试官可能会追问为什么不用vector老实说在机器人开发里C数组用得越来越少了。vector更安全、更灵活还能动态扩容。唯一的缺点是有一点点性能开销但在大多数场景下这点开销可以忽略不计。C数组什么时候用嵌入式开发里内存特别紧张的时候。比如STM32上跑一个控制算法RAM只有几十KB你用vector的话动态内存分配可能会出问题。这时候用C数组更稳妥。但如果是写ROS2节点、处理点云数据、做SLAM我强烈建议用vector。代码更安全也更容易维护。面试的时候你能说出这个区别说明你有实际工程经验。数组越界最隐蔽的bug数组越界是C/C里最常见的bug之一。int arr[10]; arr[10] 42; // 越界了这段代码能编译通过能运行但行为是未定义的。可能什么都没发生可能程序崩溃可能覆盖了其他变量的值导致一些莫名其妙的bug。我见过最离谱的一个case是之前在某做人形机器人的团队。他们的机器人跑着跑着关节角度突然跳变摔了一跤。查了三天最后发现是某个数组越界覆盖了关节控制器的参数。这种bug特别难排查因为越界的时候不会报错程序照样跑。等到出问题的时候你已经不知道是哪里越界了。怎么避免用vector的at()方法越界的时候会抛异常std::vectorint arr(10); arr.at(10) 42; // 抛出std::out_of_range异常或者用调试工具比如AddressSanitizer编译的时候加-fsanitizeaddress越界的时候程序会立即崩溃告诉你哪里出了问题。面试的时候如果你能主动提到这些调试工具面试官会觉得你有实战经验。真的。字符串处理C风格 vs std::string字符串在C里也有两种写法C风格的char*和STL的std::string。同样的道理在机器人开发里我强烈建议用std::string。C风格字符串的问题在于你需要手动管理内存手动计算长度手动拼接一不小心就缓冲区溢出。char str1[20] Hello; char str2[20] World; strcat(str1, str2); // 如果str1str2超过20就溢出了而std::string会自动管理内存不用担心溢出std::string str1 Hello; std::string str2 World; std::string str3 str1 str2; // 自动扩容安全在机器人开发里字符串用得最多的地方是日志输出、参数配置、通信协议。比如ROS2的topic名字、服务名字都是字符串。rclcpp::Node::make_shared(my_robot_node);这种地方用std::string省心多了。不过有个地方C风格字符串还是会用到嵌入式系统。比如你要跟某个传感器通信协议规定的是固定长度的字节数组这时候用char[]更直接。面试的时候你能说出这个区别说明你懂底层也懂工程实践。数组作为函数参数值传递还是引用传递这个问题面试的时候特别喜欢问。void process(int arr[]) { // arr是值传递还是引用传递 }答案是数组作为函数参数时会退化为指针。所以实际上是传递的指针是值传递但传递的是地址。这意味着你在函数里修改数组的内容原数组也会被修改。void modify(int arr[]) { arr[0] 999; } int data[10] {0}; modify(data); // data[0]现在是999这个特性在机器人开发里很有用。比如你要处理一个大的点云数据不想拷贝一份就可以直接传数组指针进去修改。但这也带来一个问题函数内部不知道数组的大小。void process(int arr[]) { // 这里不知道arr有多大 }所以通常的做法是把数组大小也传进去void process(int arr[], int size) { for (int i 0; i size; i) { // 处理arr[i] } }或者用vector它自带size()方法void process(std::vectorint arr) { for (int i 0; i arr.size(); i) { // 处理arr[i] } }面试的时候如果你能主动提到数组退化为指针这个特性面试官会觉得你对C的理解比较深。多维数组机器人数据结构的标配机器人开发里多维数组用得特别多。图像是二维数组点云是二维数组每个点有x、y、z栅格地图是二维数组关节角度是二维数组多个关节每个关节多个采样点。C风格的多维数组int grid[100][100]; // 100x100的栅格地图 grid[50][50] 1; // 标记某个格子为障碍物vector的多维数组std::vectorstd::vectorint grid(100, std::vectorint(100, 0)); grid[50][50] 1;或者用一维vector模拟二维数组性能更好std::vectorint grid(100 * 100, 0); grid[50 * 100 50] 1; // 手动计算索引这种写法在性能敏感的场景下用得比较多比如SLAM里的栅格地图更新。面试的时候如果你能说出多维数组的几种实现方式和各自的优缺点面试官会觉得你有优化意识。给正在准备面试的你一点建议数组和字符串真的是最基础的数据结构了。但基础的东西往往最能看出一个人的编程习惯。我面试的时候看候选人写数组代码主要看几点边界条件对不对、有没有越界风险、字符串处理安不安全、函数参数传递方式对不对。这些细节做好了说明这个人写过规范的代码有工程素养。怎么提高我的建议是把C数组和vector的区别搞清楚知道什么时候用哪个。然后去看看开源的机器人代码比如PCL、ORB-SLAM看看人家是怎么处理数组和字符串的。最的是养成好习惯。能用vector就不用C数组能用at()就不用[]能用std::string就不用char*。这些习惯一旦养成能帮你避免很多低级bug。如果这篇文章对你有帮助欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。「机器人软件开发面试·从入门到精通」连载系列上一篇第4篇 循环结构for/while——机器人数据采集的重复逻辑 下一篇预告第6篇 函数定义与调用——代码复用的起点有任何问题欢迎评论区留言我会尽量回复。