一开始用一分钟做自我介绍,我之前对自我介绍这方面还准备了一些,准备的稿子要说完的话肯定大于一分钟,所以说的时候自己选择性删了一点,由于多练了几遍,自我介绍说的挺流畅。然后就开始问问题,都是一些基础的问题,但是有好多都不会,虽然是第一次,但是过后感觉还是学的不够,基础问题问完问项目,我讲的是双车追逐系统,项目也有点简单,但是这也是我仅有的一个完整的项目了。
一面结果是没过,因为抽到了复活卡,所以可以进行二面,但是该总结还是要总结,合抱之木,生于毫末;九层之台,起于累土。一点一点的努力吧。
面试问到的问题有:内存对齐、常量指针和指针常量、什么是大端存储和小端存储、堆和栈的区别、什么是内存泄漏、野指针、网段和路由的概念、初始化一个链表、链表和数组的区别、TCP和UDP的区别、TCP传输怎么保证可靠性、解释一下什么是二叉树的高度、Linux gcc编译命令。将这些问题记录一下,并补充些新的一些基础知识。
1.内存对齐
内存对齐规则是按照成员的声明顺序,依次安排内存,其偏移量为成员大小的整数倍,0看作任何成员的整数倍,最后结构体的大小为最大成员的整数倍。(和sizeof一起考)
2.常量指针和指针常量
常量指针和指针常量如果要仔细写的话可以写好多,这里只总结我的一些理解。
对于指针int *p; *p是指针的值,p是指针的地址。
int *a 和 *a的初始化不一样,int *a是声明一个指针,而 *a是指针的值,所以初始化的时候,应是int *a = &b或 a = &b。
在C/C++中,常量指针的声明是:
① const int *p;
②int const *p;
这两种都是常量指针的声明。
下面看一个例子:
#include"stdio.h"
void main()
{
int a = 123;
int b = 345;
const int *p = &a;
printf("%d\n",*p);
// *p = 345; //错误:常量指针的值不能改变
p = &b; //正确:指向的地址可以改变
printf("%d\n",*p);
}
结果:
常量指针就是指针的值不可改变,但是指针的指向可以改变,即对常量指针的指针值进行赋值的时候,只能通过“&变量”赋值,不能通过 *p = 345;这种形式赋值。
常量指针的用途:①在调用函数的时候,形参是常量指针,只准使用形参,不准改变形参的值 ②顺便记录一下指针在参数传递的另一个作用,在调用函数的时候,系统要给函数分配一段栈空间来保存形参以及函数的局部变量,当传递的形参是一个很大的结构体时,如果使用传值,则形参在栈中需要占很大的空间,但如果使用传指针,则形参在栈中占的空间就只有4字节(在32位编译器中,64位编译器是8字节)。
在C/C++中,指针常量的声明:
int a;
int *const b = &a;
指针常量所指向的地址不能改变,但是其所指向地址中的值可以改变,这一点和数组名有异曲同工之妙,至于用途,暂时不清楚。
#include "stdio.h"
void main()
{
int a=345,c;
int *const b = &a;
printf("%d\n",*b);
// b = &c; //错误: 指向的地址一旦初始化就不能再指向其他地址。
*b = 123; //正确:可以改变这个指针的值
printf("%d\n",*b);
}
结果:
3.堆(stack)和栈(heap)的区别
这里说的堆和栈是内存中的“堆区”和“栈区”。堆区就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作(即不会自动释放;),栈区存放函数的参数值、局部变量等,由编译器自动分配和释放。 堆区是动态分配的,栈区是由系统自动分配的。
堆和栈空间申请后系统的响应:
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆。
C语言的内存模型分为5个区:栈区、堆区、静态区、常量区、代码区。每个区存储的内容如下:
①栈区:存放函数的参数值、局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。栈内存分配运算内置于CPU的指令集,效率很高,但是分配的内存量有限。
②堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。
③静态区:全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后,由系统释放。
④常量区:常量存储在这里,不允许修改。
⑤代码区:存放函数体的二进制代码。
栈在不同的系统中的增长方向是不一样的,但是栈的结构决定了它是一个先进后出的模型,所以和我们函数调用的过程是类似的,最先调用的函数总是最后返回,而最后调用的函数则是最最先返回,也就后调用先返回。
C语言在进行函数的调用的时候,常常会传递给被调函数一些参数,如果传递的参数少的话,就可以将参数保存在寄存器中,如果传递的参数过多的话,就将参数保存在栈中。
4.内存泄露
内存泄漏:在堆上分配的内存,如果不再使用了,就应该及时释放,以便后面其他地方可以重用。而在 C 语言中,内存管理器不会自动回收不再使用的内存。如果忘了释放不再使用的内存,这些内存就不能被重用了,这就造成了内存泄漏。
5.野指针
在C/C++等语言中,悬空指针(Dangling Pointer)指的是:一个指针的指向对象已被删除,那么就成了悬空指针。野指针是那些未初始化的指针。有时也把野指针和悬空指针通称悬空指针
概念:野指针指向了一块随机内存空间,不受程序控制。如指针指向已经被删除的对象或者指向一块没有访问权限的内存空间,之后如果对其再解引用的话,就会出现问题。
野指针产生的原因:
①指针定义时未被初始化:指针在被定义的时候,如果程序不对其进行初始化的话,它会指向随机区域,因为任何指针变量(除了static修饰的指针变量)在被定义的时候是不会被置空的,它的默认值是随机的。
②指针被释放时没有被置空:我们在用malloc开辟内存空间时,要检查返回值是否为空,如果为空,则开辟失败;如果不为空,则指针指向的是开辟的内存空间的首地址。指针指向的内存空间在用free()或者delete(注意delete只是一个操作符,而free()是一个函数)释放后,如果程序员没有对其置空或者其他的赋值操作,就会使其成为一个野指针。
③指针操作超越变量作用域:不要返回指向栈内存的指针或引用,因为栈内存在函数结束的时候会被释放。
规避方法:
①初始化指针时将其置为NULL,之后再对其进行操作。
②释放指针时将其置为NULL,最好在编写代码时将free()函数封装一下,在调用free()后就将指针置为NULL。
要想彻底地避免野指针,最好的办法就是养成一个良好的编程习惯。
6.什么是大端和小端存储
看一个例子:0x12 34 56 78在内存中的表示形式为:
①大端模式:
低地址 -----------------> 高地址
0x12 0x34 | 0x56 0x78
②小端模式:
低地址 ------------------> 高地址
0x78 0x56 | 0x34 0x12
具体可以参见这篇文章:大端和小端
7.数组和链表的区别
①数组便于查询和修改,但是不方便新增和删除。
②链表适合新增和删除,但是不适合查询。
8.TCP和UDP的区别及TCP怎么保证传输的可靠性
TCP和UDP的区别:
TCP是面向连接的、面向字节流、对系统的资源要求多、是可靠传输,UDP是面向无连接的、面向数据报、对系统的资源要求少、是不可靠传输。
对于TCP怎么保证传输的可靠性,刚开始我还以为要说三次握手啥的,没想到下来一看还不是。
TCP协议保证数据传输可靠性的方式主要有:校验和、序列号、确认应答、超时重传、连接管理(三次握手四次挥手)、流量控制、拥塞控制。
9.二叉树深度和高度的区别
不同的资料对于树的深度和高度的描述有些不一样,一样的就是树的深度是由上到下(根结点到叶结点),树的高度是由下往上(从叶结点到根结点)。有的资料规定树的高度和深度是一样的,但是有的资料规定树的高度看就看树有几层,从层数最深的叶子结点开始数,作为第一层。
对于树的叶子结点的高度和深度,叶子结点的深度就是从根结点到某一叶子结点的层数,具体是多少也要看根结点定义为第0层还是第1层。对于叶子结点的高度,从离叶子结点的子树中离这个叶子结点最远的一个叶子结点开始数(具体也是看从0开始数还是从1开始数)。
具体可以参考这篇文章:树的高度和深度
10.网段和路由的概念
参考网络层
11.初始化一个链表
参考线性表的链式存储
12.Linux 命令
这个就不多说了,多用,熟能生巧。
最后就是二面的一些问题了,一上来面试官问我都做了哪些准备,因为这个二面我是抽到复活卡才进到二面的,而且班上另一个同学说二面没问技术,所以我就没有做技术方面的准备,然后我就说除了一些技术准备,主要是在网上找关于二面会问到的问题,自己也准备了一些要问的问题,然后面试官问我准备了啥会问到的问题,我就说比如职业规划呀什么的,然后面试官就说,那你说一下你未来三年的职业规划吧,然后我说了我准备的那些,后来越想越觉得我说的离谱,竟然说到了嵌入式和网络安全方面的,不多说了。然后面试官又说咱再聊聊你的项目吧,问我这个项目有什么创新点,很无奈,当时做双车追逐的时候还是个辣鸡,能完成基本功能就很不错了,所以这块感觉又说崩了,然后就面试官就突然想要结束面试,问我还有什么问题,我问,您能不能对 我这次面试做个评价,面试官说,那你感觉你怎么样呢,我:???
我感觉这次二面能帮到后来的同学就是,我问面试官这个岗位的候选人应该要具备什么能力?面试官说,除了要善于学习、总结和拥有执行能力外,要具备的还有实践能力强,多做实践,还说在西安这里他们在硬件设计和FPGA这方面做的多,所以多了解一些FPGA方面的知识是有好处的。
先写到这,以后回顾时有问题再补充。诺瓦这个公司挺好的,奈何这是我第一次面试,而且我还菜。没过其实非常能接受,过后总结经验,查漏补缺,继续努力,长路漫漫,其修远兮,唯上下求索。