Feeds:
文章
评论

Archive for 四月, 2010

比如比较两个数的大小 : 一般我们都习惯了这样写: #define MAX(a,b) (((a)>(b))?(a)b)) //实际上宏参数计算两次 可是宏是有副作用的, 比如下面这个例子: MAX(a++,b) 又如何呢? 所以kernel里面的gcc扩展提供了很好的办法: #define MAX_CHECK(x,y) \ //宏参数仅仅计算一次 ({ \ typeof(x) __x = (x); \ typeof(y) __y = (y); \ (void) (&__x == &__y); \ (__x>__y) ?__x:__y ;\ })注意上面的是语句表达式(就是 用() 括起来) , 当if(MAX_CHECK(10,20) ) 是没有副作用的。 typeof 是个宏, 取出变量的类型 当然上面的宏 按照kernel里面的写法也可以写成这样: #define MAX_CHECK2(x,y) \ do{ \ typeof(x) __x [...]

Read Full Post »

在电子BBS讨论区上溜达,看到一个有趣的帖子,整个帖子内容如下: 纯C51复位功能函数:一个大三学生,让人又爱又怕 现单列复位部分如下: main() { unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0×32}; // 复位代码 (*((void (*)())(rst)))(); // 执行上一行代码,将rst数组当函数调用 } 本来我告诉他嵌入如下代码: clr a push acc push acc reti 结果他却玩了前面哪一段,而数组rst[]中的内容恰恰是上面的汇编机器码,他的做法是将rst数组的数据当作代码保存,然后采用绝对地址方式指向该数组,将该数组中的代码当作函数来运行。居然通过了! 我觉得有问题,我说即使如此,那绝对地址调用也应该写成(*((void (*)())(&rst)))()才对呀,结果他反驳说,那样的话,rst的地址就会当成参数传递给这个绝对地址函数,而实际LJMP调用的地址并非rst的地址,而是一个不确定的地址。于是我按照自己的说法尝试了一下,看看汇编结果,还真的是将rst的地址传递给了R1 R2,而绝对函数最终LJMP到了 一个莫名其妙的地址上去了,死翘! 看来C真是一匹不容易驾驭的野马,这个大三学生理解力在我之上,我30多岁的人了,干了这么多年还没他的境界呢,唉,人家才学了几天啊,翻了几天书就这么厉害了,服了! l 首先分析帖子的C语言代码 第一句定义一个数组rst[],数组内数据就是完成复位功能的汇编机器码,具体对应关系 为:clr a == 0xe4、push acc == 0xc0,0xe0、reti ==0×32 第二句是一个函数指针的用法,函数指针用法稍微有点复杂,可参看本人著的书,,以 下为快速入门讲解。 定义一个返回值是空函数指针的定义形式如下: void (*p) ( ) 当把函数指针赋值后,就能通过函数指针调用函数,调用形式如下, (*p) ( ); 或等价的简化形式: p ( [...]

Read Full Post »

Follow

Get every new post delivered to your Inbox.