嵌入式经典笔试题

1、堆和栈的区别

堆上的空间是手动分配和释放的,栈上的空间是自动分配与释放的。

栈空间是有限的,堆空间是很大的自由储存区

2、全局变量与局部变量的区别

  • 作用域不同:全局变量作用域为整个程序,局部变量作用域为当前语句块。
  • 内存存储方式:全局变量在全局数据区,局部变量储存在栈上。
  • 生命周期不同:全局变量的生命周期跟程序一样,局部变量随着语句块的结束而结束。
  • 当局部变量和全局变量同名时,优先使用局部变量,使用全局变量要用域成员运算符。

3、结构体与联合的区别

  • 结构体与联合都是由不同的数据类型组成,但在任何时刻,联合只存在一个被选中成员,结构体的所有成员都存在。
  • 在结构体中,各成员占有自己的存储空间,总大小等于各成员大小之和
  • 在联合中,所有成员共用一块存储空间,其大小等于联合中最大的成员的大小

4、数组与指针的区别

  • 数组要么在静态储存区,要么在栈上被创建。数组名对应着一块内存,其容量与地址在生命周期内保持不变
  • 指针可以随时指向任意类型的内存块,它的特征是可变。比数组灵活,但也危险

5、指针函数与函数指针的区别

指针函数是一个函数,它返回值是一个指针。

函数指针是一个指针,这个指针所指的对象是一个函数

6、常量与变量的区别

常量是只读不可写,变量可读可写;常量必须初始化,变量可以不初始化

常量不可以寻址,它的地址不可以赋给非常量指针。变量可以寻址;常量的效率比变量高

7、指针自增自减与变量自增自减有什么区别

指针自增自减是改变指针所指的对象。变量自增自减是改变变量的值

8、#error的作用是什么

编译程序时,只要遇到#error就会跳出一个编译错误

9、#include<file.h>和#include "file.h"的区别

#include<file.h>表示该文件存在编译器指定的标准头文件存放处

#include "file.h" 表示该文件在用户当前的工作目录下

10、头文件中的 ifndef/define endif 的作用

防止头文件被重复引用

11、常见的条件语句的比较的写法

  • bool类型 if(flag)建议使用 ; if(flag == true) 不建议使用,true值的定义没有统一的标准
  • int if(value != 0)建议使用;if(value)不建议使用,会让人误认为是bool类型
  • float if(x>-EPSINON && x<EPSINON)建议使用;if(x == 0.0)不建议使用,精度问题
  • 指针 if(p == NULL)建议使用,强调p为指针;if(p==0)不建议使用,会让人误解为int类型

12、用#define实现宏并求最大值最小值

#define MAX(x, y) ((x)>(y))?(x):(y)

#define MIN(x, y) ((x)<(y))?(x):(y)

13、break语句与continue语句有什么区别

continue语句只能出现在循环语句内,表示结束本次循环;break语句还可以出现在switch语句内,表示结束switch语句,在循环语句内表示结束整个循环

14、static关键字

  • 用于全局变量:表示该变量是静态全局变量。作用域为当前文件
  • 用于函数:该函数为静态函数,只能在本文件中调用。静态函数在内存中只有一份,普通函数在内存中维持一份拷贝
  • 用于局部变量:为静态局部变量,只初始化一次,之后调用函数都是上次函数退出的值。即改变变量的生存周期为整个程序运行时间段内
  • static成员函数:表示这个函数属于此而不属于此类的任何对象,不能访问非静态变量和函数,该函数在该类中是唯一的
  • static成员变量:表示该变量属于此类而不属于此类的任何对象,该变量的初始化在类体外

15、const关键字

  • 修饰一般常量:修饰符可在类型说明符前,也可在类型说明符后,
    • 例如:int const x=2; const int x = 2;
  • 修饰数组: 修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。
    • 例如列如: int const a[5]={1, 2, 3}; 或: const int a[5]={1, 2, 3};
  • 修饰常指针
    • const int *A;//const 修饰指针指向的对象,指针可变,指针指向的对象不可变
    • int const *A;//const 修饰指针指向的对象,指针可变,指针指向的对象不可变
    • int *const A; //const 修饰指针, 指针不可变,指针指向的对象可变

16、const 与宏的区别

答:

编译时刻 宏:在预编译时刻 const:在编译时刻

编译检查 宏不会编译检查 const:有编译检查

宏的好处: 宏可以定义函数、方法等等 const:不可以

宏的坏处: 大量使用宏,会导致预编译的时间过长

17、带参宏与函数的区别

答:

  • 1、 处理时间不同: 宏是在预编译时刻,函数是在运行时刻。
  • 2、 带参宏没有参数类型,函数具有参数类型。
  • 3、 带参宏不分配内存,函数需要分配内存。
  • 4、 宏会使函数边长,函数不会。
  • 5、 宏不占用运行时间,函数在调用时刻和返回时刻占用时间。

18、局部变量与全局变量有什么区别

答:局部变量储存在栈区,全局变量储存在静态数据区。

19、引用与指针的区别

答:

  • 1、 非空区别:指针可以指向 NULL,引用必须指向某个对象。
  • 2、 可修改区别:指针可以指向不同的对象,引用总是指向初始化的对象
  • 3、 合法性区别:在使用指针之前要判断指针是否为 NULL,引用不需要判断

20、malloc()和 calloc()的区别

  • 1、 malloc 和 colloc 都是在堆上申请动态内存空间。
  • 2、 malloc 只有一个参数,即要分配内存大小
  • 3、 calloc 函数有两个参数,分别是元素的个数与元素的大小。
  • 4、 malloc 不能对内存初始化, calloc 对内存的没一位初始化为零

21、strcpy sprint memcpy 函数的区别

答: strcpy 函数操作的对象是字符串 ,完成从源字符串到目的字符串的拷贝

sprint 函数操作的对象不限于字符串,是实现其它数据类型吸纳高字符串的转化。 方法中需要指定源对象的数据类型,如果源对象是字符串,也可以实现字符串的拷贝功能。

memcpy 内存的拷贝,实现将一个内存的内容复制到另一个内存块。内存块由首地址及长度决定。

22、strcpy 函数为什么要返回 char*类型

答:增加代码的灵活性,方便其它函数直接调用。

23、new delete 与 malloc free 的联系与区别

答:

  • 1、 都是在堆上进行动态内存的分配与释放。
  • 2、 new delete 是 c++的运算符, malloc free 是函数
  • 3、 new 会自动调用对象的构造函数,返回相应的类型。
  • 4、 malloc 只会申请指定大小的内存,返回 void*类型(不能初始化对象)。
  • 5、 delete 与 new 配对,会调用析构函数。
  • 6、 free 与 malloc 配对,只是内存的释放,不会调用析构函数。

24、关于静态内存的分配和动态内存的分配的区别及过程

  • 1、 静态内存的分配是在编译时刻完成的,不占用 CPU 资源;动态分配内存是在运行时刻完成,分配与
  • 释放占用 CPU 运行时间,
  • 2、 静态内存分配是在栈上的,动态内存是在堆上分配的。
  • 3、 动态内存分配需要指针或引用数据类型的支持,而静态内存分配不需要。
  • 4、 静态内存的分配是按计划分配的,在编译前确定内存块大小,动态内存分配运行时按需分配。
  • 5、 静态内存的分配是把内存的控制权交给了编译器,动态内存的分配是把内存的分配交给了程序员。
  • 6、 静态分配内存的效率比动态分配内存的效率高,因为动态内存的分配与释放需要额外的开销;动态内存管理水平严重依赖于程序员的水平,处理不当容易造成内存泄露。

25、一个短小的函数在 C 和 C++中分别用什么实现

答:在 C++中用内联函数实现,在 C 中用宏实现。

26、在 c++程序中调用被 C 编辑器变异后的 函数,为什么要加 extern C?

答: c++语言支持函数的重载, c 语言不支持函数的重载。编译后参数的名字不同,函数被 c++编译器编译后产生的名字为函数名加参数列表类型名之类的名字。而 c 编辑器编译后产生的名字为函数名。

27、一个由 C/C++编译器编译过的程序有那几个部分

答:

  • 1、 栈区:由编译器自动编译,释放;储存函数参数的值,局部变量的值等。其操作方式类似于数据结构中的栈
  • 2、 堆区:由程序员分配与释放,如果程序员没有释放在程序结束时可能由 OS 释放,储存结构类似于链表。
  • 3、 全局区全局变量和静态变量储存在这一块,初始化的全局变量与静态变量在一块,未出货的全局变量存放在静态变量相邻的一块。程序结束后由系统释放。
  • 4、 文字常量区 常量字符串存放在此处,程序结束后系统自动释放
  • 5、 程序代码区:存放函数体的二进制代码

28、C 与 C++有什么区别

答: C 语言是面向结构化的编程语言,他是面向过程的, C 语言编程考虑的是实现的过程; C++是面向对象的, C++编程考虑的是整个程序的模型。

29、虚析构函数与析构函数的区别

答: 加上 virtual 后,就会先执行子类的析构函数, 再执行基类的析构函数。

不执行析构函数,就可能存在内存泄露。

30、面向对象与面向过程的区别

答:面向对象是一种以对象为中心的编程思想,以消息进行驱动,程序 = 对象 + 消息;

面向过程是一种以应用为中心的编程思想,以算法进行驱动,程序 = 算法 + 数据

31、“extern c”的作用

答: extern c 是告诉编译器这段代码以 C 语言进行编译

32、类成员函数的重载,重写,隐藏的区别

答:

重载:在一个类中,方法名相同,参数列表不同。与 virtual 无关

重写:也叫覆盖 指在子类中定义一个与父类中的虚函数并且实现。

隐藏:派生类函数与基类函数名相同,但参数不同。或者参数相同但父类不是虚函数。

33、多态的实现?

答:简单的说是子类实现了父类的虚函数,父类指针不仅可以调用自己的这个函数,当指向子类时可以调用子类的这个函数,从而实现了多态。

34、多态的作用?

答:实现了动态联编, 使程序的运行效率更高,更容易维护。

35、默认的拷贝构造函数的缺陷

答:存在着浅拷贝问题,主要是在内中定义指针变量时,当调用默认拷贝构造函数时,只拷贝地址,两个对象的指针变量指向同一块地址空间。

36、简述成员函数、全局函数、友元函数的区别

成员函数只能由实例化对象调用(静态成员函数除外)全局函数可在任何时刻调用,

友元函数可以让类的友元类对象调用。(友元类或函数可以访问私有成员函数和变量)。

37、什么时候会使用复制(拷贝)构造函数

答 :

1、 一个对象以值的方式传入函数体

2、 一个对象以值传递的方式重函数中返回

3、 一个对象需要通过另外一个对象初始化

38、什么是容器

答:容器是存放特定对象的集合,在 STL 中有顺序容器和关联容器两种。

39、什么是顺序容器,有那几种

答:顺序容器是指将一组具有相同类型的对象,以严格的线性形式组织在一起的容器。包括 vector、deque、list 等 3 种顺序容器。

40、什么是关联容器,有哪几种

答:关联容器可以通过键值对来查找和读取元素的容器,在 STL 中有四个关联容器,分别是: map、 set、multimap、 multiset。

41、什么是异常

答:异常就是程序运行时出现的不正常,它可能会导致系统无法正常运行甚至停止运行等严重的情况

42、如何抛出异常

答:在 C++中,系统通过 try 快和异常处理构成异常处理机制,其中通过 catch 语句来捕获运行时的异常,并且执行异常处理,通过 throw 语句来抛出异常

43、软件测试的方法有那几类

答:两类,黑盒:针对系统功能做测试,白盒:测试函数的功能

44、TCP 与 UDP 的区别

TCP

面向连接

数据是安全的

效率低

基于数据流

可靠

UDP

面向无连接

数据是不安全的

效率高

基于数据报文

不可靠

45、TCP/IP 协议的主要层次结构

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

46、epoll 的 LT,ET 模式

二者的差异在于 level-trigger 模式下只要某个 socket 处于 readable/writable 状态,无论什么时候进行

epoll_wait 都会返回 socket;而 edge-trigger 模式下只有某个 socket 从 unreadable 变为 readable 或

从 unwritable 变为writable 时, epoll_wait 才会返回 socket。

47、三次握手

答:三次握手即建立 TCP 连接,就是指建立一个 TCP 连接时,需要客户端和服务端发送 3 个包以确认连

接的建立。在 socket 编程中,这一过程由客户端指向 connect 来出发。

1)第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

2)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

3)第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

48、四次挥手

答: 四次挥手是终止 TCP 连接,就是指端口一个 TCP 连接时,需要客户端和服务端发送四个包以确认连接的断开,在 socket 编程中,这一过程由客户端或服务端任意一方执行 close 来触发。

 1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

 2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

 3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

 4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手

49、为什么建立连接是三次握手,关闭连接却是四次挥手

答: 这是因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报

文里发送给客户端。而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接

收数据,己方也未必全部数据都发送给对方了,所以己方可以立即 close,也可以发送一些数据给对方后,

再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送。

50、进程与线程的区别

答:线程是进程的一个执行单元,也是进程可以调度的实体。与进程的区别:

(1)线程是调度和分配分配的基本单位,进程时拥有资源的基本单位。

(2)进程可以并发执行,同一进程的多个线程也可以并发执行。

(3)进程是拥有资源的独立单位,线程不拥有系统资源,但可以访问进程的资源。

(4)在创建进程时,系统要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程的开销。

归纳:进程有用独立的资源、有PCB;线程有独立PCB,但没有独立的资源,可以与同进程的其它线程共享数据。

51、TCP/UDP工作在哪一层?

答:传输层

52、tcp/udp的使用场合?

(1)对数据可靠性的要求。tcp适用于可靠性高的场合,udp适用于可靠性低的场合

(2)应用的实时性。tcp有延时较大,udp延时较小

(3)网络的可靠性。网络不好的情况下使用tcp,网络条件好的情况下,使用udp

发布了21 篇原创文章 · 获赞 5 · 访问量 2257

猜你喜欢

转载自blog.csdn.net/PTA123/article/details/105211563