C-C++练习7

来源:互联网 发布:rgb转换为cmy算法 编辑:程序博客网 时间:2024/06/17 22:50

1、下面程序有没有问题,为什么?

__interrupt double compute_area (double radius){    double area = PI * radius * radius;    printf("/nArea = %f", area);    return area;}


中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准 C支持中断。具代表事实是,产生了一个新的关键字__interrupt。上面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR)。
这个是经典的面试题,它的问题如下:
1.ISR 不能返回一个值。
2.ISR 不能传递参数。
3.由于重效率问题不要在 ISR 中做浮点运算。
4.不要在 ISR 中做 IO 操作。
(printf 这个函数是一个 IO 函数 很多 IO 函数都是不可重入的。也就是说如果在执行 printf 的时候这个中断产生了,那么是不是 printf 又被调用了?
另外的原因就是 printf 实在太慢了( printf 的实现其实还调用了 sprintf 和 write 系统调用))
下面就有一个问题了,既然 ISR 有那么多限制,那么如果我们真的需要做这些事,那么怎么办呢?
好,下面就要提一下系统设计的一些技巧。在一些大型系统中 ISR 一般只是做一些投递消息的操作。比如发生了中断,然后就只是向一个队列中插入一个中断号,这样就可以在其他的线程中处理这个中断,这样就绕开了限制。



2、编译期和运行期的疑问?
).一个程序哪些东西可以在编译期就确定?
2).一个程序哪些东西要等到运行期才确定?
3).比如:int x = 100; x是在什么时间被赋值的?


1、静态的赋值,比如 int a = 2; sizof的计算等。编译器会尽自己最大的努力在编译阶段确定足够多的东西
2、实在是在编译阶段无法确定的东西,比如指针的多态表现,对内存的动态分配等
3、int x = 100 显然是编译期
编译期分配内存并不是说在编译期就把程序所需要的空间在内存里面分配好,而是说在程序生成的代码里面产生一些指令,由这些指令控制程序在运行的时候把内存分配好。不过分配的大小在编译的时候就是知道的。
而运行期分配内存则是说在运行期确定分配的大小,存放的位置也是在运行期才知道的。



3、为什么ABC不行?

#define ABC #pragma message("aaa")int main(){    //#pragma message("aaa") //这样是可以的    ABC //这样就不行    return 0;}

当然不行,#define 中,不能嵌套其它预编译的代码。



4、题目:实现一个袖珍型计算器,假设已经从界面编辑框读入两个数 op1 和 op2,和一个操作符 per( +, -, *, /) ,可以用 switch 来实现,代码如下:
switch(per)
{
case ADD:
result = add(op1,opt2);
break;
case SUB:
result = sub(op1,op2);
break;
……
}
如果对于一个新奇的有上百个操作符的计算器,这个 switch 将会很长。有没有什么办法可以缩短这个代码量,看起来简洁明了呢?


大家想想如何做 这个确实在大型软件系统中常用。
老师:
第 0 步:
定义操作函数

int add(int p1, int p2){    return p1 + p2;}int sub(int p1, int p2){    return p1 - p2;}

第1步:
定义函数指针

typedef int(*pFunc)(int, int);

第2步
定义结构体

struct Operation{    int op;    pFunc func;};

第3步
定义操作列表

static struct Operation OpArray[] ={    { '+', add },    { '-', sub },};

第四步
定义 run 函数

int run(int op, int p1, int p2){    int ret = 0;    int i = 0;    for(i=0; i<sizeof(OpArray)/sizeof(*OpArray); i++)    {        if( OpArray[i].op == op )        {            ret = OpArray[i].func(p1, p2);        }    }    return ret;}

如果你现在要增加一个新的操作乘法,你会如何修改上面的代码呢?只需要修改第0和3步就可以了。这样来写代码是不是对于后面的扩展很有好处了,只需要多定义一个操作函数 和 把操作函数添加到操作列表中就可以了。

其他的解法:
1、申明并实现单个功能函数:

Type add(Type, Type);Type sub(Type, Type);Type mul(Type, Type);……

2、初始化函数指针数组:

Type (*oper_func[])(Type,Type) = {add,sub,mul,...};

3、求计算结果:

result = oper_func[add/sub/mul](op1,op2);
0 0
原创粉丝点击