嵌入式c题目2
九、中断(Interrupts):
11、中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展——让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}
这个函数有太多的错误了,以至让人不知从何说起了:
1)ISR 不能返回一个值。
2)ISR 不能传递参数。
3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需
要让额外的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。
此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。
4)与第三点一脉相承,printf()经常有重入和性能上的问题。
十、代码例子(Code examples):
12 、下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
((a+b) > 6) ? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。
13、评价下面的代码片断:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
十一、动态内存分配(Dynamic memory allocation):
14、尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?
答案:内存碎片,碎片收集的问题,变量的持行时间等等。!
附加问题:
下面的代码片段的输出是什么,为什么?
char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");
把0值传给了函数malloc,得到了一个合法的指针之后,这就是上面的代码,该代码的输出是"Got a valid pointer"。
十二、Typedef :
15、Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字,也可以用预处理器做类似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;
以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构体s的指针。哪种方法更好呢?为什么?
答案是:typedef更好。
思考下面的例子:
dPS p1,p2;
tPS p3,p4;
第一个扩展为
struct s * p1, p2;
上面的代码定义p1为一个指向结构体s的指针,p2为一个实际的结构体,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。
十三、晦涩的语法:
16、C语言同意一些令人震惊的结构,下面的结构是合法的吗?如果是,它做些什么?
int a = 5, b = 7, c;
c = a+++b;
上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b;
因此,这段代码持行后a = 6, b = 7, c = 12。
浙公网安备 33010602011771号