发新帖我要提问
12
返回列表
打印

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

[复制链接]
楼主: zq1987731
手机看帖
扫描二维码
随时随地手机跟帖
21
china_fog| | 2011-2-14 11:56 | 只看该作者 回帖奖励 |倒序浏览
我觉得是方便调试,12楼说的意思

使用特权

评论回复
22
yuyixuanta| | 2011-2-14 15:16 | 只看该作者
都是经典的习惯
实质上都是都是应付编译器的。

使用特权

评论回复
23
sxhhhjicbb| | 2011-2-14 22:04 | 只看该作者
if(1)结构,我常用于调试.
#define DHD_ERROR(args)      do {printf args;} while (0)第二个args打上(args)比较多.
有时多层宏时会有异常.

使用特权

评论回复
24
zyboy| | 2011-2-15 14:07 | 只看该作者
do while(0)在宏定义中的应用,在linux源码常能看到

这是一个奇怪的循环,它根本就只会运行一次,为什么不去掉外面的do{..}while结构呢?我曾一度在心里把它叫做“怪圈”。原来这也是非常巧妙的技巧。在工程中可能经常会引起麻烦,而上面的定义能够保证这些麻烦不会出现。下面是解释:

假设有这样一个宏定义

#define macro(condition) \

if(condition) dosomething()

现在在程序中这样使用这个宏:

if(temp)
    macro(i);
else
    doanotherthing();

一切看起来很正常,但是仔细想想。这个宏会展开成:

if(temp)
    if(condition) dosomething();
else
    doanotherthing();

这时的else不是与第一个if语句匹配,而是错误的与第二个if语句进行了匹配,编译通过了,但是运行的结果一定是错误的。

为了避免这个错误,我们使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。


另一个讲解

这是为了含多条语句的宏的通用性
因为默认规则是宏定义最后是不能加分号的,分号是在引用的时候加上的

比如定义了一个宏fw(a,b),那么在c文件里一定是这样引用
fw(a,b);

如果不用do...while,那么fw就得定义成:
#define fw(a,b) {read((a));write((b));}   
那这样fw(a,b);展开后就成了:
{read(a);write(b);};
最后就多了个分号,这是语法错误

而定义成do...while的话,展开后就是:
do{read(a);write(b);}while(0);  完全正确
所以要写一个包含多条语句的宏的话,不用do...while是不可能的

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
电子write_cai + 1
25
GNMXD| | 2011-7-14 09:45 | 只看该作者
妙!

使用特权

评论回复
26
江南shui乡| | 2011-7-14 10:34 | 只看该作者
24楼解释的好啊!
所谓的“去耦”啊。

使用特权

评论回复
27
alex1120| | 2011-7-15 16:54 | 只看该作者
do {} while(0)在TI的某个程序中见到过

使用特权

评论回复
28
linbei1988| | 2011-7-15 17:02 | 只看该作者
24楼解释的很好!

使用特权

评论回复
29
weibestww| | 2011-9-2 22:30 | 只看该作者
这样做是万能的,防止在编译的时候由于宏定义为函数时编译不过,也就是后面分号的问题。

使用特权

评论回复
30
ayl439| | 2012-6-14 09:31 | 只看该作者
mark

使用特权

评论回复
31
fjzzclc| | 2012-6-14 10:20 | 只看该作者
学习了,进步了

使用特权

评论回复
32
wukunshan| | 2012-6-14 16:27 | 只看该作者
加入do{...}while(0)句,说明大括号里的代码在不同的场合执行的次数不同,这都是为了移植后更改方便。如果要让大括号里的代码反复执行多次,只需在宏定义里就改个数字就可以了,在整个程序里用到这段代码的地方都改变了,移植后更改是不是很方便?代码前加条件语句if(1)也是同样的道理。
在函数前面加(void),是把函数的返回值强制转换为无类型,用在函数有返回值但不使用返回值的场合,否则编译器会警告。

使用特权

评论回复
33
amwrdfe| | 2012-6-14 16:39 | 只看该作者
ls想多了,
do{.....}while(0),是为了保持代码的通行性
应付if xxxx else xxxx这类场合。

使用特权

评论回复
34
xxlin1984| | 2012-6-15 15:31 | 只看该作者
不会绕弯弯的,一律if{xxx}else{xxx}:D

使用特权

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

本版积分规则