打印

怪异的C语言风格,谁能道出其中精髓?

[复制链接]
5569|33
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zq1987731|  楼主 | 2011-1-22 19:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近接到个任务,把ThreadX上的Wifi驱动移植到RexL4上本着研究的心态尽量拖时间读OS的源代码玩...
发现些有趣的习惯——

众所周知,有这么种宏:
#define    FUNC()    do{XXXXXX}while(0)
这个有什么用就不废话了
接着有趣的习惯出现了:
#define    FUNC()    do(if(1)XXXXXX}while(0)
嗯...相当神奇...注意那个if(1)

另外有几个function,原型为void Func(void);
调用时方式如下——
(void)Func1();
(void)Func2();
......
注意前面的(void)

如此习惯妙在哪大家看得出么?
...

相关帖子

沙发
hgjinwei| | 2011-1-22 22:04 | 只看该作者
不懂,望赐教

使用特权

评论回复
板凳
highgear| | 2011-1-23 12:26 | 只看该作者
if(1) while(0) 是为了多语句的macro定义
(void) 为了避免未定义变量的警告

使用特权

评论回复
地板
highgear| | 2011-1-23 12:47 | 只看该作者
要求严格的程序不允许有警告,(void) 是为了避免未使用的变量的警告,而不产生额外的代码。

使用特权

评论回复
5
zq1987731|  楼主 | 2011-1-23 13:51 | 只看该作者
呵呵~~原来这样...
不过关于第1点
举个例——
#define DHD_ERROR(args)                do {if (1) printf args;} while (0)
那么,和下面的语句比起来又有何不同呢?
#define DHD_ERROR(args)                do {printf args;} while (0)

使用特权

评论回复
6
liang7143| | 2011-1-23 16:40 | 只看该作者
#define DHD_ERROR(args)                do {if (1) printf args;} while (0)
这种还真没有见过~~
请高手赐教

使用特权

评论回复
7
原野之狼| | 2011-1-23 20:04 | 只看该作者
void的问题显示地说明下该函数无返回值,只是提示下阅读者。
if(1)的问题,提供的信息有限,不好说,我写程序也会使用if(1),不过这是用在“蒙骗”编译器的。

使用特权

评论回复
8
jqlilee| | 2011-1-24 00:24 | 只看该作者
我想先弄明白
#define DHD_ERROR(args)                do {printf args;} while (0)

#define DHD_ERROR(args)                {printf args;}
有什么好处?

使用特权

评论回复
9
ayb_ice| | 2011-1-24 08:35 | 只看该作者
宏不管怎么释都只是替换而已
"#define DHD_ERROR(args)                do {printf args;} while (0)"
这本质是还个带参数的宏定义,好处就是什么样的参数都合法,这是针对编译器而言的(对参数宏本身都是合法的),
也就是说不管是简单的参数(比如常量),还是复杂的表达式都可以,特别适合参数又是个宏定义的情况,甚至参数是多重宏定义的情况
可能一般还是很难理解的,最好是查看源文件中的调用情况分析
while (0)好理解了,就是只执行一次do的语句,本质就是C语句

使用特权

评论回复
10
butlet| | 2011-1-24 10:45 | 只看该作者
编译器不同生成的汇编代码可能不同,但是感觉这种代码很没意义,写一种更纯粹的,不是更好

使用特权

评论回复
11
ayb_ice| | 2011-1-24 10:52 | 只看该作者
LS
这和汇编代码有什么关系

使用特权

评论回复
12
heuyck| | 2011-1-24 11:10 | 只看该作者
我想先弄明白
#define DHD_ERROR(args)                do {printf args;} while (0)

#define DHD_ERROR(args)                {printf args;}
有什么好处?
jqlilee 发表于 2011-1-24 00:24


如果你在宏内多写几句,两者就不一样了。
比如{printf args;} 换成{printf "1";printf "2";}
调用时用 for(x,y,z) DHD_ERROR("hello");
如果不用do while会导致printf "1";和printf "2";有不一样的处理。

if(1)我经常用来调试两块代码的比较,只改0、1,不用注释来注释去。
是不是有可能用来开关调试输出的?

(void)Func1();要求严格的程序不允许有警告,(void) 是为了避免未使用的变量的警告,而不产生额外的代码。
这个我就不知道了,没见过这样的警告。

使用特权

评论回复
13
zq1987731|  楼主 | 2011-1-24 12:00 | 只看该作者
To jqlilee: #define DHD_ERROR(args)                do {printf args;} while (0)比
#define DHD_ERROR(args)                {printf args;}的好处么...

比如有如下调用:
if(a == b)
    DHD_ERROR(args);
else
    Func();
同时用上面两者展开,前者是——
if(a == b)
    do {printf args;} while (0);
else
    Func();
当然运行正确,但如果如下展开,红色分号注意到没?这时候else找谁去?
if(a == b)
    {printf args;};
else
    Func();


To butlet:
这和汇编没有关系,这年头没有哪个编译器会傻到if(1),do{}while(0)都会视若无睹,“写得更纯粹”,那编译出来结果仍旧完全一样,同时可读性直线下降,有弊无利。


To heuyck:
可能就是这个原因了,用if(1)和(0)来调试不同代码,不过#if 0和#if 1岂不是更好...呵呵
另外具体调用方式举个例——
DHD_ERROR(("The Value is %d", x));
给我的感觉是为了兼容不支持C99的老编译器而这么做的,展开后自然就变成
do {if(1)printf ("The Value is %d", x);} while (0);
当然GNU的C用多了就发现...写这OS的人也挺无奈的

使用特权

评论回复
14
wljs012| | 2011-1-24 16:38 | 只看该作者
如果是作者的坏习惯呢?呵呵

使用特权

评论回复
15
highgear| | 2011-1-24 23:13 | 只看该作者
do while(0) 是为了多语句 macro. 例如:
#define a(x) b(x);c(x)

a(x); //没有问题
if (y==1)
   a(x);    //不正确。
else

用  #define a(x) do { b(x); c(x); } while (0) 则没有问题。

至于 void 不知道  func1 是函数还是函数指针。如果是函数, 则如原野之狼所说。否则, 很可能是避免警告, 如:
void func(x* func1)
{
   (void) func1;     
}
某些compiler 对从未使用的参数会提出一个warning, 而很多公司要求不允许有任何警告。

使用特权

评论回复
16
Simon21ic| | 2011-1-25 03:50 | 只看该作者
do while (0)里的if(1)可能是配置用的,如果要运行就if(1),不要就if(0)
也有可能是以前的代码遗留

使用特权

评论回复
17
ayb_ice| | 2011-1-25 08:33 | 只看该作者
LS
不管是if(0)还是if(1),do后面的语句都会执行的

使用特权

评论回复
18
tsacy| | 2011-1-25 18:13 | 只看该作者
:)还是不动啊~!~

使用特权

评论回复
19
hgjinwei| | 2011-2-13 14:34 | 只看该作者
宏就是替换,其他花式都是浮云。

使用特权

评论回复
20
e掾木| | 2011-2-14 11:43 | 只看该作者
do{}while(0)在可移植、软硬件同步分组开发的场合很绝妙。
我常将那些跟硬件相关的部分都这样定义,扇出到哪一个IO口或者某个跟硬件相关的部分先定义成do{ }while(0)这样一个空架子,以后慢慢填充。例如:
  #define   RS485_TX_EN()  do{}while(0)
  #define  AlarmPortOn()    do{}while(0)

编译器很聪明地将这个结构编译出来,看不到所谓的循环结构。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:PCB Layout(1~12,HS/RF),802.11abgn,EFT/ESD/Surge...EMC:GR1089/60950/ITU... Linux/ThreadX/RexL4/Nucleus Driver(ARM11/A8/MIPS/i.MX...) 软硬兼修不可能?呵呵...井底之蛙们...

95

主题

759

帖子

3

粉丝