分享7道最近常问的嵌入式面试题
1. 关键字static的作用是什么?为什么static变量只初始化一次?
本文引用地址:https://www.eepw.com.cn/article/202404/457326.htm· 修饰局部变量:使得变量变成静态变量,存储在静态区,存储在静态区的数据周期和程序相同,在main函数开始前初始化,在退出程序时销毁(无论是局部静态还是全局静态)。
· 修饰全局变量:全局变量本身就是存储在静态区,因此static并不能改变其存储位置。但是,static限制了其链接属性,被static修饰的全局变量只能被该包含该定义的文件访问(即改变了作用域)
· 修饰函数:是的该函数只能在包含该函数定义的的文件中被调用,对于静态函数,申明和定义需要放到同一个文件夹中。
· 修饰成员变量:使用static修饰类的数据成员使其成为类的全局变量,会被类的所有对象共享,包括派生类的对象,所有的对象都只维持同一个实例。因此,static成员必须在类外进行初始化(初始化格式:int base::var=10;),而不能在构造函数内进行初始化,不过也可以使用const修饰的static数据成员在类内初始化。
· 修饰成员函数:使用static修饰成员函数,使这个类只存在这一份函数,所有对象共享该函数,不含this指针,因而只能访问类的static成员变量。
静态成员是可以独立访问的,也就是说,无需创建任何对象实例就可以访问。例如可以分装某些算法,比如数学函数,如sin、cos等,这些函数本就没必要属于某一个对象,所以从类上调用更好。
注意:不可以用const static修饰成员函数。
对于所有的对象(不仅仅是静态对象),初始化都只有一次,而由于静态变量具有“记忆”功能,初始化后,一直都没有被销毁,都会保存在内存区域中,所以不会再次初始化。
存放在静态区的变量的生命周期一般比较长,一般与整个源程序“同生死、共存亡”,所以它只需初始化一次。
2. 关键字voliate作用和含义/使用场景?
volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
一般用处:
· 并行设备的硬件寄存器(如状态寄存器):存储器映射的硬件寄存器通常也要加 voliate,因为每次对它的读写都可能有不同意义。
· 中断服务程序中修改的供其它程序检测的变量,需要加volatile:当变量在触发某中断程序中修改,而编译器判断主函数里面没有修改该变量,因此可能只执行一次从内存到某寄存器的读操作,而后每次只会从该寄存器中读取变量副本,使得中断程序的操作被短路。
· 多任务环境下各任务间共享的标志,应该加volatile:在本次线程内, 当读取一个变量时,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当内存变量或寄存器变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致 。
· 一个参数既可以是const还可以是volatile吗?可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
· volatile的本意是“易变的”由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化,但有可能会读脏数据。当要求使用volatile声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。
3. sizeof和strlen的区别,使用场景?
sizeof() 和 strlen() 的主要区别在于:
· sizeof() 是一个运算符,而 strlen() 是一个函数。
· sizeof() 计算的是变量或类型所占用的内存字节数,而 strlen() 计算的是字符串中字符的个数。
· sizeof() 可以用于任何类型的数据,而 strlen() 只能用于以空字符 '