笔试经历

前段时间考一个公司就有这个题,无奈只回答出前两点。html


中断是嵌入式系统中重要的组成部分,这致使了不少编译开发商提供一种扩展—让标准C支持中断。具表明事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。程序员

__interrupt double compute_area (double radius)面试

{ double area = PI * radius * radius;多线程

printf(” Area = %f”, area);函数

return area;post

}性能

这个函数有太多的错误了,以致让人不知从何提及了:测试

1). ISR 不能返回一个值。若是你不懂这个,那么你不会被雇用的。优化

2). ISR 不能传递参数。若是你没有看到这一点,你被雇用的机会等同第一项。spa

3). 在许多的处理器/编译器中,浮点通常都是不可重入的。有些处理器/编译器须要让额处的寄存器入栈,有些处理器/编译器就是不容许在ISR中作浮点运算。此外,ISR应该是短而有效率的,在ISR中作浮点运算是不明智的。

4). 与第三点一脉相承,printf()常常有重入和性能上的问题。若是你丢掉了第三和第四点,我不会太为难你的。不用说,若是你能获得后两点,那么你的被雇用前景愈来愈光明了。


这个公司还有个题,这个题答出来了。之前看过别人的源代码这么写过。

嵌入式系统常常具备要求程序员去访问某特定的内存位置的特色。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。


这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着我的风格不一样而不一样。典型的相似代码以下:

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa55;

一个较晦涩的方法是:

*(int * const)(0x67a9) = 0xaa55;

即便你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。


这是另外一道题,没写的很满意。没有把BIT3宏定义,唉,日常我都会写成宏的,那天怎么就。。。。。

嵌入式系统老是要用户对变量或寄存器进行位操做。给定一个整型变量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 (0×1<<3)

static int a;

void set_bit3(void)

{ a |= BIT3;

} void clear_bit3(void)

{ a &= ~BIT3;

} 一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是能够接受的。我但愿看到几个要点:说明常数、|=和&=~操做。


多任务中被几个任务共享的变量。唉,回答的本身见解。彻底是错的。额。。。volatile,搞嵌入式必须掌握的啊。

回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员常常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是否是直正懂得volatile彻底的重要性。

1). 一个参数既能够是const还能够是volatile吗?解释为何。

2). 一个指针能够是volatile 吗?解释为何。

3). 下面的函数有什么错误:

int square(volatile int *ptr)

{ return *ptr * *ptr;

} 下面是答案:

1). 是的。一个例子是只读的状态寄存器。它是volatile由于它可能被意想不到地改变。它是const由于程序不该该试图去修改它。

2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

3). 这段代码的有个恶做剧。这段代码的目的是用来返指针*ptr指向值的平方,可是,因为*ptr指向一个volatile型参数,编译器将产生相似下面的代码:

int square(volatile int *ptr)

{ int a,b;

a = *ptr;

b = *ptr;

return a * b;

} 因为*ptr的值可能被意想不到地该变,所以a和b多是不一样的。结果,这段代码可能返不是你所指望的平方值!正确的代码以下:

long square(volatile int *ptr)

{ int a;

a = *ptr;

return a * a;

}



关键字volatile有什么含意 并给出三个不一样的例子。

回答的出来,可是看看上面的题吧,本身仍是没有真正理解。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都当心地从新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

1). 并行设备的硬件寄存器(如:状态寄存器)

2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)

3). 多线程应用中被几个任务共享的变量

相关文章
相关标签/搜索