嵌入式软件工程师面试题收录(2)

最近收集了许多嵌软的面试题,内容都是在很多文章中剪下来的!

目录

1.OSI七层模型有哪七层?TCP/IP四层模型有哪四层?每一层有什么常用协议?

OSI七层模型:

TCP/IP四层模型:

2.从在浏览器地址栏中输入www.baidu.com到看到百度首页,这个过程中间经历了什么?

1)客户端浏览器获取用户在地址栏输入的域名。

2)客户端浏览器将域名发送给DNS域名系统,请求解析。

3)DNS解析域名得到相应的IP,返回给客户端浏览器。

4)客户端浏览器根据IP向服务器发起TCP三次握手,建立TCP连接。

5)客户端浏览器向服务器发送HTTP请求,请求百度首页。

6)服务器通过HTTP响应向客户端浏览器返回百度首页文件。

7)释放TCP连接。

8)客户端浏览器解析HTML文件,根据文件内容获取CSS、JS等资源文件,将页面渲染展示给用户。

3.编写strcat函数(字符追加)

4.实现把字符串转化为整数

5.写一个程序验证系统的大小端存储格式

6.大小端格式问题

7.如何判断一个byte数据中有多少bit为1?

8.进程间通信的方式有哪些?

9.堆和栈的区别

10.C++内存区域分为5个区,分别为栈、堆、自由存储区、全局/静态存储区和常量存储区。请说出各区存储的是什么?

11.进程和线程的区别

12.printf可以接受多个参数吗,为什么,请写出printf的原型。

13.什么是堆栈,简述为什么需要堆栈?

14.请列举常用的串行通信方式(两种以上),并简述串行通信和并行通信的不同之处、优缺点。

15.引用和指针的区别

16.常用端口对应协议

17.ARP和RARP协议是什么?

18.已知数组table,用宏求元素个数

19.什么是平衡二叉树?

20.全局变量和局部变量的区别

21.数组和链表的区别

22.死锁的四个条件和处理方法

23.进程调度策略

24.如何引用一个已经定义过的全局变量

25.全局变量可不可以定义在可被多个.c文件包含的头文件中?为什么?

26.语句for(;1;)有什么问题?它是什么意思?

27.程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。

28.用两个栈实现一个队列的功能?要求给出算法和思路!

29.堆栈溢出一般是由什么原因导致的?

30.写出float x与’零值’比较的if语句

31.IP地址的编码分为哪两部分?

32.阅读下面代码,写出答案

33.阅读下面代码,写出答案

34.C和C++的不同

35.5[“abcdef”]能编译通过,请问编译后的结果是什么?

36.线程同步的方法

37.for( i = 0 ; i<2,i<3,i<4 ; i++ ) printf(“%d,”,i);输出什么

38.int *a= (int *)2; printf(“%d”,a+3);求出a的值

39.中断活动的全过程大致为?

40.如何防止同时产生大量的线程?

41.操作系统的内存分配一般有哪几种方式,各有什么优缺点?

42.写一个快速排序算法


面试不仅仅是C、C++的问题,相关涉广,还有系统、网络和数据库等。

1.OSI七层模型有哪七层?TCP/IP四层模型有哪四层?每一层有什么常用协议?

OSI七层模型:

TCP/IP四层模型:

        应用层、传输层、网络层、数据链路层。

2.从在浏览器地址栏中输入www.baidu.com到看到百度首页,这个过程中间经历了什么?

按照时间顺序:

1)客户端浏览器获取用户在地址栏输入的域名

2)客户端浏览器将域名发送给DNS域名系统,请求解析

3)DNS解析域名得到相应的IP,返回给客户端浏览器

4)客户端浏览器根据IP向服务器发起TCP三次握手,建立TCP连接

5)客户端浏览器向服务器发送HTTP请求,请求百度首页

6)服务器通过HTTP响应向客户端浏览器返回百度首页文件

7)释放TCP连接

8)客户端浏览器解析HTML文件,根据文件内容获取CSS、JS等资源文件,将页面渲染展示给用户。

附参考链接:http://t.csdn.cn/I3QGLhttp://t.csdn.cn/I3QGL

3.编写strcat函数(字符追加)

#include "assert.h"//将源字符串加const,表明其为输入参数,保持值不变
char *mew_strcat(char *dest,const char *src) 
{assert(dest&&src);      //对源地址和目的地址加非0断言//if(!(dest && src))	return NULL;  //与上行代码等同//循环体内的++可以使指向字符串结束标志'\0'while(*dest != '\0')     dest++;                                    while( (*dest++=*src++) != '\0' );return dest;
}

为什么要char * 的返回值

主要是为了实现链式表达式。如strcpy(buf,strcat(dest,src));。

strcpy()函数的原型是char *strcpy(char *strDest,const char *strSRC)。其中,strDest是目标字符串,strSRC是源字符串。

对于断言关键字assert,下面进行简单讲解:

#include "assert.h"

void assert( int expression );

assert的作用是现计算表达式 expression,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。

使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。

在调试结束后,可以通过在包含 #include 的语句之前插入 #define NDEBUG 来禁用 assert 调用。

4.实现把字符串转化为整数

int new_atoi(char *str)
{int sum=0,status=1;if(str == NULL) /*判断是否为空*/    return 0;   if(*str == '-') /*判断是否负号*/{status = -1;str++;}while( (*str) != '\0' ){sum = sum*10 + ((*str)-'0');str++;}return sum * status;
}

5.写一个程序验证系统的大小端存储格式

/*方法1*/
typedef union{int i;char c;
}my_union;int checkSystem1(void)
{my_union u;u.i = 1;//return (u.i == u.c);    //返回1表示小端,返回0表示大端return (u.c);             //返回1表示小端,返回0表示大端
}/*方法2*/
int checkSystem2(void)
{int  i=1;return *(char *)&i;            //返回1表示小端,返回0表示大端
}

6.大小端格式问题

大端存储模式:数据的低位,存放在地址的高位。
小端存储模式:数据的低位,存放在地址的低位。

我们的pc机一般都是小端模式,在低位置存放的就是低位数据。

void checkCpuMode(void)
{int     i = 0x12345678;      //i为4字节,32位。char    *c = (char *)&i;     //c位1字节,8位。//将i字符化得c,判断c的8位存储的是i数据哪里的位置。if(*c == 0x78)printf("little endian"); //小端格式elseprintf("big endian\n"); //大端格式}

7.如何判断一个byte数据中有多少bit为1?

int select(unsigned char data)
{int count=0;while(data!=0){count +=  (data & 1);data >>= 1;}return count;
}

8.进程间通信的方式有哪些?

 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。IPC 的方式通常有管道(包括无名管道和有名管道FIFO)、消息队列、信号量、共享内存、套接字Socket、Streams 等。其中 Socket 和 Streams 支持不同主机上的两个进程 IPC。

管道

FIFO

消息队列

信号量

共享内存

套接字

附参考链接:http://t.csdn.cn/z67KUhttp://t.csdn.cn/z67KU

9.堆和栈的区别

1)申请方式不同:栈由系统自动分配,堆是由人为自行开辟(new,delete)

2)申请的大小不同:栈是从高地址向低地址分配的,分配空间较小,堆是由低地址向高地址分配的,空间较大。

3)申请效率不同:栈由系统分配,分配速度较快,堆一般较慢

4)队列和栈都是线性存储结构,栈是”先进后出”,队列是”先进先出”,都占用连续的地址空间,而堆不是连续的地址空间,堆随意存储,很容易产生内存碎片,造成内存泄露。

5)分配方式不同:堆都是动态分配,而栈分静态和动态分配。静态分配由编译器完成,比如局部变量的分配。动态分配由alloca函数进行。但栈的动态分配和堆是不同的,它的动态分配由编译器进行释放,无需我们手工实现。

10.C++内存区域分为5个区,分别为栈、堆、自由存储区、全局/静态存储区和常量存储区。请说出各区存储的是什么?

全局变量和静态变量存储在全局/静态存储区。常量存储在常量存储区。

栈存储的是函数参数值、局部变量等。

11.进程和线程的区别

进程:指在系统中正在运行的一个应用程序。程序一旦运行就是一个进程。进程是资源分配的最小单位。

线程:程序执行的最小单位。

这里借阅了其他文章的想法,其他博主写的很好。

做个简单的比喻:进程=火车,线程=车厢
线程在进程下运行(单纯的车厢无法运行)
一个进程可以包含多个线程(一辆火车可以有多个车厢)
不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)
进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-"互斥锁"
进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”。

附参考链接:线程和进程的区别是什么? - 知乎看了一遍排在前面的答案,类似”进程是资源分配的最小单位,线程是CPU调度的最小单位“这样的回答感觉太…https://www.zhihu.com/question/25532384

12.printf可以接受多个参数吗,为什么,请写出printf的原型。

int printf(const char *fmt,...);

13.什么是堆栈,简述为什么需要堆栈?

 栈,又称堆栈,是计算机中最常用的一种数据结构,保存数据的一块连续内存;比如函数的调用是用堆栈实现的。

14.请列举常用的串行通信方式(两种以上),并简述串行通信和并行通信的不同之处、优缺点。

串行通信

并行通信

传输原理

数据按位顺序传输

数据各个位同时传输

优点

占用引脚资源少

速度快

缺点

速度相对较慢

占用引脚资源多

列举

UART、SPI、IIC、RS485、CAN

SDIO、FSMC

异步通信和同步通信;并行速度快,串行口线间干扰小。

15.引用和指针的区别

1)指针是一个实体,而引用仅是个别名;
2)引用必须在声明时初始化,之后不可变;指针可变;

3)引用不能为空,指针可以为空;
4)引用没有 const,指针有 const;
5)“sizeof 引用”==所指向变量(对象)的大小,
而“sizeof指针”==指针本身(所指向的变量或对象的地址)的大小;
6)指针和引用的自增(++)运算意义不一样;

//对于第五点,32位编译器
#include
int main()
{char a  = 30;char *p = &a;char &b = a;cout<

16.常用端口对应协议

17.ARP和RARP协议是什么?

地址解析协议(ARP)的作用是将IP地址转换成MAC地址;反地址解析协议(RARP)则负责将MAC地址转换成IP地址。

18.已知数组table,用宏求元素个数

#define  COUNT(table)  ( sizeof(table)/sizeof(table[0]) )
#define  COUNT(table)  ( sizeof(table)/sizeof(*(table)) )

两种方式都可以,意思都一样。 

19.什么是平衡二叉树?

当且仅当两个子树的高度差不超过1时,这个树是平衡二叉树。

20.全局变量和局部变量的区别

全局变量,储存在全局/静态存储区.进入main函数之前就被创建.生命周期为整个源程序; 
局部变量,在栈中分配.在函数被调用时才被创建.生命周期为函数内。 

全局变量和静态变量存储在全局/静态存储区;栈存储的是函数的参数值,局部变量的值等。

21.数组和链表的区别

数组:顺序存储,插入删除效率低,访问元素效率高。

链表:随机存储,插入删除效率高,访问元素效率低。

22.死锁的四个条件和处理方法

1)互斥条件:一个资源每次只能被一个进程使用。    
2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 
3)不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。  
4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。  
解决死锁的方法:银行家算法。 

23.进程调度策略

先进先出算法,最短CPU运行期优先调度算法,轮转法,多级队列方法

24.如何引用一个已经定义过的全局变量

答:可以用引用头文件的方式,也可以用extern关键字。

如果用引用头文件方式来引用某个在头文件中声明的全局变量,假定你将那个变量写错了,那么在编译期间会报错。

如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。 

25.全局变量可不可以定义在可被多个.c文件包含的头文件中?为什么?

答:可以,在不同的C文件中以static形式来声明同名全局变量。

26.语句for(;1;)有什么问题?它是什么意思?

答:没问题,和while(1)相同。

27.程序的局部变量存在于(堆栈)中,全局变量存在于(静态区)中,动态申请数据存在于()中。

28.用两个栈实现一个队列的功能?要求给出算法和思路!

 设2个栈为A,B, 一开始均为空. 
 入队: 将新元素push入栈A; 
 出队: 

        1)判断栈B是否为空; 
        2)如果不为空,则将栈A中所有元素依次pop出并push到栈B; 
        3)将栈B的栈顶元素pop出;

29.堆栈溢出一般是由什么原因导致的?

没有回收垃圾资源。 

30.写出float x与’零值’比较的if语句

if(x>0.000001&&x<-0.000001);

31.IP地址的编码分为哪两部分?

IP地址由两部分组成,网络号和主机号。

32.阅读下面代码,写出答案

main()
{  int a[5]={1,2,3,4,5};int *ptr=(int *)(&a+1); //&a相当于变成了行指针,加1则变成了下一行首地址printf("%d,%d",*(a+1),*(ptr-1));}

*(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5

33.阅读下面代码,写出答案

unsigned char *p=(unsigned char *)0x0801000
unsigned char *q=(unsigned char *)0x0810000
p+5 =?    0x0801005
q+5 =?    0x0810005 

34.C和C++的不同

1)c++源于c,c++最重要的特性就是引入了面向对象机制,class关键字。
2)c++中,变量可以在任何地方声明;c中,局部变量只能在函数开头声明。
3)c++中,const型常量是编译时常量;c中,const常量只是只读的变量。
4)c++有&引用;c没有。
5)c语言的main函数可以递归调用;c++中则不可以
6)c中,void *可以隐式转换成其他指针类型;c++中要求现实转换,否则编译通不过

35.5[“abcdef”]能编译通过,请问编译后的结果是什么?

 printf("%d\n",5["abcdef"]);输出'f'的ACSII值,如果是4["abcdef"]则输出'e'的ACSII的值。

36.线程同步的方法

信号量、条件变量、互斥锁

37.for( i = 0 ; i<2,i<3,i<4 ; i++ ) printf(“%d,”,i);输出什么

0,1,2,3

需要注意的是,对于条件判断,只要其一还能通过,就能执行。

38.int *a= (int *)2; printf(“%d”,a+3);求出a的值

答案是2+3*4=14;int类型地址加1 相当于加4个字节

39.中断活动的全过程大致为?

1)中断请求:中断事件一旦发生或者中断条件一旦构成,中断源提交“申请报告”,与请求CPU暂时放下目前的工作而转为中断源作为专项服务。(发出中断请求)

2)中断屏蔽:虽然中断源提交了“申请报告”,但是,是否得到CPU的响应,还要取决于“申请报告”是否能够通过2道或者3道“关卡”(中断屏蔽)送达CPU。(通过中断屏蔽)

(相应的中断屏蔽位等于1,为关卡放行;反之相应的中断屏蔽位等于0,为关卡禁止通行);

3)中断响应:如果一路放行,则CPU响应中断后,将被打断的工作断点记录下来
  (把断点地址保护到堆栈),挂起“不再受理其他申请报告牌”(清除全局中断标志位GIE=0),跳转到中断服务子程序。(进行中断响应)

4)保护现场:在处理新任务时可能破坏原有的工作现场,所以需要对工作现场和工作环境进行适当保护。即SCB_VTOR的XPSR、PC、LR、R12、R3~R0由硬件自动压入适当的堆栈中。如果当响应中断时,当前的代码正在使用PSP,则压入PSP,即使用线程堆栈。否则压入MSP,使用主堆栈。一旦进入了中断服务,就将一直使用主堆栈;

5)调查中断源:检查“申请报告”是由哪个中断源提交的,以便作出有针对性的服务;

6)中断处理:开始对查明的中断源进行有针对性的中断服务;

7)清除标志:在处理完毕相应的任务之后,需要进行撤消登记(清除中断标志),以避免造成重复响应;

8)恢复现场:恢复前面曾经被保护起来的工作现场,以便继续执行被中断的工作;

9)中断返回:将被打断的工作断点找回来(从堆栈中恢复断点地址),并摘下“不再受理其他申请报告牌”(GIE=1),继续执行原先被打断的工作。 

40.如何防止同时产生大量的线程?

方法是使用线程池,线程池具有可以同时提高调度效率和限制资源使用的好处,线程池中的线程达到最大数时,其他线程就会排队等候。

41.操作系统的内存分配一般有哪几种方式,各有什么优缺点?

 定长和变长。
 变长:比较灵活,但是易产生内存碎片。
 定长:灵活性差,但分配效率较高,不会产生内存碎片。 

42.写一个快速排序算法

原理:找一个基准值,分别将大于和小于基准值的数据放到基准值左右两边,即一次划分。由于处在两边的数据也是无序的,所以再用同样的划分方法对左右两边的序列进行再次划分,直到划分元素只剩1个时结束。

这里借阅了其他文章的想法,其他博主写的很好。

void quick_sort(int a[],int start,int end)
{if(start < end){int i = start,j = end,temp = a[start];while(i < j){while(i < j && a[j] < temp) j--;if(i < j) a[i++] = a[j];//把小于基准值放在左边while(i < j && a[i] >= temp) i++;if(i < j) a[j--] = a[i];//把大于基准值放在右边}a[i] = temp;quick_sort(a,start,i-1);quick_sort(a,i+1,end);}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部