一面
面试感受
这次诺瓦的面试是我下半年的第一次面试,准备的很不充分吧。今年的招聘都是线上进行的,我和室友是在同一天面试,他比我早三个钟头,由于实验室可能比较吵,所以我们就在宿舍面试。好巧不巧的是,我们是相同的两个面试官。我们宿舍贴了砖墙风格的墙纸,那两位面试官可能一眼就看了出来,这两位同学可能是同一个宿舍。因为我们两个的个人介绍,学习经历以及项目比较类似,加上面试官提的问题和之前提问舍友的很类似,我觉得在面试官面前和室友回答的一样会很别扭,心态或多或少受到些影响。
面试的过程有四十多分钟,整个面试的流程先是进行自我介绍,然后面试官提问,再就是项目讲解。先问了C语言、计算机网络、数据结构有关的问题。刚开始是一些热身问题,比较简单,后面的话涉及到了内存、指针,问的比较深。实际上我编码经验比较少,也不清楚相关概念,这里把我问懵了。之后问了链表和数组的区别,我头一天还看到这个题目了,整理的挺全的,但是当时没有说完全。回答了数组元素的存储密度高,需要一大块连续的内存空间,而链表对存储空间的要求不高,是一块一块存储的,也说了一些其他的。但是面试官反问我,两者在内存中怎样排布的?我半天没有搞清楚他想问的点在哪,就回答了数组元素存储在栈区,而链表存储在堆区。之后问了些网络的内容,还问我了不了解Linux。果然,Linux是绕不开的。
之后就是讲项目了,让我根据这五个方面分开来讲。
- 项目的背景
- 项目的人员构成
- 自己负责的内容
- 怎么分工的
- 最终实现了什么功能
因为面我室友也是这样,项目问的特别细,所以我提前按照这些模块划分好了,我就准备一条一条的讲下去。但是在我介绍整体框图,介绍我是怎样剖析这个问题的,都用到了什么,他就打断我,问我光电传感器的原理,用到的LCD的型号,是用什么接口来控制LCD的。之后就是问那些传感器的原理,常用的协议。在协议以及模块这边问的特详细,比如说问IIC的时序图,IIC数据传输的最大速度,以及应该配置给它多大的频率。平常我觉得只是会用就行了,没太关注过这些,现在好后悔啊。我觉得我还需要把项目重新梳理一遍,把各个模块的具体特性记住。
另外,我觉得有个问题非常重要,这个问题回答好了肯定很加分。”在编写程序的过程中有遇到过什么困难吗?是怎样解决这个困难的?”下去好好琢磨一下这个问题。
后面就是在我面试过程中具体提到的问题以及部分个人见解。
面试主要问题
- 用C语言写死循环(多种写法实现)
- while语句
- for语句
- 无条件跳转goto语句
- do-while语句
while(1){}
for(;;){}
loop:
//code
goto loop;
do
{}
while(1);
- 常用的选择语句有哪些?它们两个有哪些区别?你平时哪个用的比较多一些?那个效率更高一些?
- if-else和switch-case
- 区别
- if-else语句更适合对于区间(范围)的判断,switch-case适合于对离散值的判断
- 所有的switch-case语句都可以用if-else来替换,反之,不是所有的switch-case语句都可以替换if-else语句,switch语句所接受的值只能是整形或枚举类型。
- switch根据一个整形值进行多路分支,并且编译器对多路分支进行优化,所以switch-case效率更高
- 内存对齐的概念?
-
什么是内存对齐?
按照成员的声明顺序,一次安排内存,其偏移量为成员大小的整数倍,0看作任何成员的整数倍,最后结构体的大小为最大成员的整数倍。 -
为什么要内存对齐?(加快CPU与内存的读取速度)
- 底层处理器的限制:对于多数处理器,每次访问的数据并不是越少越好。不是所有的硬件平台都能访问任意地址上的任意数据
- 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。因为为了访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存访问只需要一次。
-
内存对齐有啥优点?
- 程序的执行效率提高:减少了访问内存的次数
- 访问范围提高:对于任意给定的地址空间,如果体系架构
- 原子性得到保障:对齐后的数据,CPU访问内存,内存中的数据总是原子性的
-
如何改变内存对齐方式?
- 使用伪指令#pragma pack(n),C编译器将按照n个字节对齐
- 使用伪指令#pragma pack(n),取消自定义字节对齐方式
- 使用__attribute__((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐
-
在在32位的系统中,占多少个字节的内存?(以下代码中,sizeof(a)的值为多少?)
short a[10] = {0};
sizeof(a);
* sizeof()对数组为 数据长度*数据类型长度
* sizeof()对指针的长度为 机器字长,32位4字节,64位8字节
* sizeof()对数据类型为 数据类型长度
* sizeof()对结构体为 结构体内存对齐后的长度
- 这个结构体,在内存中占多少个字节?有没有办法减小它在内存中占用大小?
struct
{
char a[11];
int b;
char c;
}A;
- 野指针产生的原因一般是什么?会造成什么后果?有什么方法可以避免野指针的出现?
- 原因?
- 指针定义时未被初始化:指针在定义的时候,如果程序不对其进行初始化,会随机指向一个区域,因为任意指针变量(static修饰的指针)的默认值都是随机的
- 指针被释放时没有置空:指针指向的是开辟的内存空间的首地址。指针指向的内存空间在用free()和delete()释放后,如果程序员没有对其进行置空或者其他赋值操作的话,就变成一个野指针。
- 指针操作超越变量作用域:不要返回指向栈内存的指针或引用,栈内存在函数结束的时候会被释放。
- 后果?
指针指向的内存已经无效了,但指针没有被置空,不一定会导致段错误(此处存疑) - 怎样避免?
- 初始化时,先将指针置为NULL,之后再对其进行操作
- 释放指针时,在调用free()后就将指针置为NULL
- 给一个单向链表,如何将这个链表反向?
- 就地反转法
H为头结点,s为待反转的结点,p为待反转结点的前驱结点
H.next = head;
ListNode p= H.next;
ListNode s= p.next;
while (s!= null) {
p.next = s.next;
s.next = H.next;
H.next = s;
s= p.next;
}
- 新建链表,头节点插入法
新建一个头结点,遍历原链表,把每个节点用头结点插入到新建链表中,最后,新建的链表就是反转后的链表。H为头结点,s为待插入的结点,p为待插入结点的前驱结点
p= s.next;
s.next = H.next;
H.next = s;
s= p;
- 链表跟数组有什么区别?在内存中是怎么排布的?
- 链表是链式的存储结构,数组是顺序的存储结构
- 链表通过指针来链接元素与元素,数组是把所有元素按次序依次存储
- 数组便于查询与修改 O(1)
- 链表适合新增和删除 O(1)
- 数组在内存中连续,链表不连续
- 数组元素在栈区,链表元素在堆区
- 网络的七层模型有哪些?IP是在哪一层?MAC?
- IP地址处于网络七层模型中的网络层,表示在哪个网络下,它是可变的
- MAC地址处于模型中的数据链路层,是硬件地址,每个设备都有一个固定的MAC地址,它是不可变的
- TCP和UDP本质上的区别是什么?TCP可以广播吗?
-
TCP(Transmission Control Protocol)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须先在双方之间建立一个TCP连接,并且提供超市重发,丢弃重复数据、流量控制等功能,保证数据能从一端传到另一端。
-
UDP(User Data Protocol)是一个简单的面向数据报的运输层协议。它不提供可靠性,只是把应用程序传给IP层数据报发送出去,但是不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发的机制,所以传输速度很快。
-
区别
-
TCP不可以进行广播,因为它是建立连接的
- 对linux有些了解吗?(无)
- 谈项目(按点说)
- 项目的背景
- 项目的人员构成
- 自己负责的内容
- 怎么分工的
- 最终实现了什么功能
- 光电传感器的原理
- LCD的型号?用什么接口来控制LCD?
- 对IIC有了解吗?介绍一下你了解的IIC。
- IIC数据传输的最大速度是多少?配置是多高的频率?对IIC的时序了解吗?
- LCD显示的时间是从哪里获得的?
- 超声波的工作原理,怎样计算距离?计算距离所用的时间是从哪里来的?
- 在项目中遇到过哪些困难?在编写程序的时候遇到过什么困难?
- 你提到的LCD模块有26个IO口,其中控制传输数据的有两根,其他的线有什么用?
- 蓝牙怎样实现的?用到的波特率是多少?波特率是什么意思?假如把波特率设置为115200,传输速度每秒钟是多少字节?
- SPI,USB,FMC外设接口?用过吗?
- SPI由几根线构成?一个主机接了三个从机,它的片选线需要怎样连接?
- SPI有几种模式?包括上升沿采样和下降沿采样。
- 有用过SPI进行过一些外设的开发吗?
- 你的SPI访问的是那个模块?那个外设?
- 在项目过程中,用过什么工具?比如万用表,逻辑分析仪、示波器?
- 电源怎样从12V降到5V?什么电源稳压模块?