1.嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
2.关键字volatile有什么含意 并给出三个不同的例子。int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;
/*加上volatile之后,CPU不去优化程序;在多任务执行中,每次变量的值发生改变之后,都去内存里面回写这个值*/
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)/*(有时硬件引起的变化,程度没有去回写寄存器,而是按照先前的值 处理)没有加volate之前*/
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) (中断嵌套)
3). 多线程应用中被几个任务共享的变量
3.一个指针可以是volatile 吗?解释为什么。
是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
4. 评价下面的代码片断:
unsigned int zero = 0;unsigned int compzero = 0xFFFF;
/*1'scomplement of zero */对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:unsignedint compzero = ~0;这一问题真正能揭露出应试者是否懂得处理器字长的重要性。好的嵌入式程序员非常准确地明白硬件的细节和它的局限。
5.下面的代码片段的输出是什么,为什么?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
该代码的输出是“Got a valid pointer”。/*在堆的每个区间的前面,有个头部用以管理这个分配的空间,所以malloc(0)!= NULL*/
6.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;
上面的代码被处理成:c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
7.为什么标准头文件都有类似以下的结构?
#ifndef __incvxworksh
#define __incvxworksh
#ifdef__cplusplus
extern "c" {
#endif
/*...*/
#ifdef__cplusplus
}
#endif
#endif/* __incvxworksh */
解答:
头文件中的编译宏
#ifndef __incvxworksh
#define __incvxworksh
#endif
的作用是防止被重复引用。为了实现c和c++的混合编程,c++提供了c连接交换指定符号extern "c"来解决名字匹配问题,函数声明前加上extern"c"后,则编译器就会按照c语言的方式将该函数编译为_foo,这样c语言中就可以调用c++的函数了。
8.请写一个c函数,若处理器是big_endian的,则返回0;若是little_endian的,则返回1
解答:
int checkcpu()
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b == 1);
}