嵌入式知识总结

专栏地址:嵌入式面经地址

1:堆和栈的区别

①栈的空间由系统自动分配或释放,堆的空间手动分配或释放

②栈的空间有限,堆上有很大的自由存储空间,malloc分配的空间在堆上,使用完后需要释放

2:static关键词的作用

①修饰局部变量,将其生命周期改为与全局变量相同,作用域不变

②修饰全局变量时, 当一个源程序由多个源文件组成时,将其作用域从整个源程序改为该源文件

③修饰函数时,表明该函数作用域为该源文件内

3:volatile关键字的作用

①与const关键词对立,表示“可变的”,修饰变量时表明该变量需要从内存单元中读取,不能直接从寄存器中拷贝

②常用于并行设备的硬件寄存器,中断服务子程序访问到的变量,多线程之间被几个任务共享变量

3.1:const关键词的作用

定义变量为常量

修饰函数的参数,表示在函数体中不能改变这个参数的值

修饰函数的返回值,表示该返回值不可变

修改常指针

4:extern关键字

①用于声明一个已在其他文件定义的变量或函数

②在c++程序中调用c编译后的函数,要加extern c的声明;因为C++要支持函数重载,而c不支持,函数被C++编译后在库中的名字与C语言的不同,C++提供 extern C来解决名字匹配问题。

5:实现strcpy函数

char *strcpy(char *strDest, const char *strSrc)
{
    if (!(strDest && strSrc))
        return NULL;
    char *ret = strDest;
    while ((*strDest++ = *strSrc++)!='\0');
    return ret;
}

6:引用和指针的区别

(1). 指针是一个变量,存储的是一个地址,引用,是原变量的别名

(2). 指针所指向的内存空间在程序运行过程中可以改变,而引用所绑定的对象一旦绑定就不能改变。(是否可变)

(3). 指针在内存中占有存储内存空间,引用相当于变量的别名,在内存中会占4字节内存

(4). 引用没有 const,指针有 const,const 的指针不可变;

(5). 指针可以空,但是引用必须绑定对象。(是否可为空)

(6). 指针可以有多级,但是引用只能一级。(是否能为多级)

引用在创建的时候必须初始化,只有在调用虚函数时,才能实现动态绑定

7:malloc的用法和注意点

该函数用于分配堆上的n个字节,并返回指向这块内存的指针,如果分配失败则返回NULL;

注意:①申请了内存空间之后,必须检查是否申请成功

②当不再使用申请的内存,必须进行释放,且释放后必须将指针置NULL,否则会导致野指针

③malloc和free配套使用,申请不释放为内存泄漏,释放多次,会导致错误

④malloc的类型是void*,使用时需要将其强制转换为需要的类型指针

8:C和C++的区别

①c面向过程,完成一件事情,按照步骤一步步完成;c++面对对象,将不同的食物看成一个对象,依靠多个对象之间的相互联系、相互操作,完成一定的功能。

②c++输入输出流不同

③c++有命名空间namespace

④c++有缺省函数,对每个函数的参数有一个初值

⑤c++函数重载,相同的函数,不同的函数列表

⑥c++有引用,c是指针,详情见标题6(引用和指针的区别)

⑦动态内存分配不同

⑧c++智能指针

⑨c++有stl,vector list等

⑩struct在c++可相当于class使用,唯一的区别是struct默认修饰词是public,calss默认修饰词是private

⑪const修饰的变量,在c中不能用于数组的下标,c++可以

9:C语言的编译过程

预处理->编译->汇编->链接,

GCC编译器的几个组成部分:预处理(cpp)、编译器(ccl)、汇编器(as)、链接器(ld)

①预处理,将所有的#include头文件以及宏定义替换成其真正的内容,gcc的预处理是预处理器cpp来完成的,得到的是文本文件。

②编译,将经过预处理之后的程序转换成特定汇编代码,得到的是.s文件

③汇编,将上一步的汇编代码转换成机器码,得到的是目标文件,是二进制格式,这一步会为每一个源文件生成一个目标文件。

④链接,将多个目标文件以及所需的库文件(.so等)链接成最终的可执行文件exe。

10.重载、重写、隐藏的区别

重载:是指同一可访问区内被声明几个具有不同参数列(参数的类型、个数、顺序)的同名函数,根据参数列表确定调用哪个函数,重载不关心函数返回类型。

隐藏:是指派生类的函数屏蔽了与其同名的基类函数,主要只要同名函数,不管参数列表是否相同,基类函数都会被隐藏。

重写(覆盖):是指派生类中存在重新定义的函数。函数名、参数列表、返回值类型都必须同基类中被重写的函数一致,只有函数体不同。

重写和重载的区别:

范围区别:对于类中函数的重载或者重写而言,重载发生在同一个类的内部,重写发生在不同的类之间(子类和父类之间)。

参数区别:重载的函数需要与原函数有相同的函数名、不同的参数列表,不关注函数的返回值类型;重写的函数的函数名、参数列表和返回值类型都需要和原函数相同,父类中被重写的函数需要有 virtual 修饰。

virtual 关键字:重载的函数可以有也可没有,重写的函数基类中必须有 virtual关键字的修饰,

隐藏和重写,重载的区别:

范围区别:隐藏与重载范围不同,隐藏发生在不同类中。

参数区别:隐藏函数和被隐藏函数参数列表可以相同,也可以不同,但函数名一定相同;当参数不同时,无论基类中的函数是否被 virtual 修饰,基类函数都是被隐藏,而不是重写。

11:智能指针

答:智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露(利用自动调用类的析构函数来释放内存)。它的一种通用实现技术是使用引用计数(除此之外还有资源独占,如(auto_ptr),只引用,不计数(weak_ptr))。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

12:内存泄漏

内存泄漏:申请了一块内存空间,使用完毕后未及时释放//由于疏忽或错误导致的程序未能释放已经不再使用的内存,造成了内存的浪费。一般是:调用了malloc/new等内存申请的操作,但缺少了对应的free/delete,

防止:

(1)计数法:使用new或者malloc时,让该数+1,delete或free时,该数-1,程序执行完打印这个计数,如果不为0则表示存在内存泄露

(2)一定要将基类的析构函数声明为虚函数

(3)良好的编码习惯,有new就有delete,有malloc就有free,保证它们一定成对出现

(4)智能指针:智能指针是 C++ 中已经对内存泄漏封装好了一个工具,可以直接拿来使用。

后果:

只发生一次小的内存泄漏可能不被注意,但泄漏大量内存的程序将会出现各种证照:性能下降到内存逐渐用完,导致另一个程序失败;

13:深拷贝和浅拷贝

(1)浅拷贝是增加了一个指针,指向原来已经存在的内存。

(2)深拷贝是增加了一个指针,并新开辟了一块空间让指针指向这块新开辟的空间。浅拷贝在多个对象指向一块空间的时候,释放一个空间会导致其他对象所使用的空间也被释放了,再次释放便会出现错误。

14:回调函数

如果把函数的指针作为参数传递给一个函数,当这个指针被用来调用其所指向的函数时,就是回调函数。简单的说:把一段可执行的代码像参传递那样传给其他代码,而这段代码会在某个时刻被调用执行,就叫做回调。如果代码立即被执行称为同步回调,如果在之后晚点的某个时间再执行,称为异步回调。

回调函数的本质是对函数指针的应用

使用回调函数,和普通函数调用区别:

1)在主入口程序中,把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,且不需要修改库函数的实现,变的很灵活,这就是解耦。

2)主函数和回调函数是在同一层的,而库函数在另外一层。如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了,这也就是在日常工作中常见的情况。

#晒一晒我的offer##数据人的面试交流地##设计人的面试记录##24届软开秋招面试经验大赏#
全部评论
红名佬带带我
点赞 回复 分享
发布于 2023-11-22 11:20 辽宁

相关推荐

10-17 10:05
已编辑
北华大学 全栈开发
牛客872465272号:掉头发了哥
点赞 评论 收藏
分享
3 11 评论
分享
牛客网
牛客企业服务