嵌入式学习小组
直播中

廉鼎琮

7年用户 897经验值
私信 关注

在C语言中关键字static的作用是什么

在C语言中关键字static的作用是什么?

用预处理指令#define 声明一个函数,输入天数得到有多少秒?

回帖(1)

余姗姗

2021-12-24 14:23:12
记录下一些自己最近去应聘嵌入式软件工程师遇到的一些笔试题,都是一些关于C/C++方面的问题和单片机方面的问题,留个纪念。


  • 用预处理指令#define 声明一个函数,输入天数得到有多少秒(忽略闰年问题)
    答:#define SECONDS_DAYS(A) (60 * 60 * 24 * A)UL
    我在这想看到几件事情:
    1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
    2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算天数中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
    3). 意识到这个表达式将有可能使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
    4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
  • 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
    答:#define MIN(A,B) ((A) <= (B)? (A) :(B) )),
    这个题目也加一个要求,不使用< > = if 等条件
    #define MIN(A,B) ((A) / (B)? (A) :(B) )),
  • 关键字static的作用是什么?
    当时只回答出了大概,什么维持不变,内部使用防止被外部使用这样子,以下是完整的:
    这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
    1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
    2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
    3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
    大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。
  • 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

__interrupt double compute_area (double radius)
{ double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
当时第一反应就写了返回值和参数。
标准答案:
这个函数有太多的错误了,以至让人不知从何说起了:
1). ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
2). ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
3). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
4). 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。
5.I2C接口里面的SDA和SCK的全称好像,是两个英文名词,当时就没写,后来面试问我不懂这个吗,有点尴尬,他跟我说了中文才知道,I2C学的时候只知道怎么用,没深入。
还遇到过一个叫我写UART、I2C、SPI、CAN总线等详细的讲解,还要画其中一个的时序图,当场去世。
6.关于单片机中常见的位运算的题目,即 |= &=~ 这两个的一些操作,有让你置位的,也有让你算一个八位数里面有多少个位是1的。
例题
嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。
对这个问题有三种基本的反应
1). 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。
2). 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到 Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。
3). 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{ a |= BIT3;
} void clear_bit3(void)
{ a &= ~BIT3;
} 一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。
7.有一个题目是关于面向对象的四大特性的,就自己百度吧,就是抽象、封装、继承、多态。
编程题:
1、单向链表取反的;
2、在一个字符串中找到第一个只出现一次的字符
3、51单片机流水灯
……
好好总结,希望自己早日找到理想的工作,目前只有一个offer,是新公司,工资待遇也不高,不是很心动,太难了,加油吧。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分