gro*_*kus 20 c kernel linux-kernel
可能的重复:
当我们定义一个宏时,do(0)有什么用?
为什么在C/C++宏中有时会出现无意义的do/while和if/else语句?
C多行宏:do/while(0)vs scope block
我已经看到了很多这样的用法,以前我是程序员想要轻松打破一段代码.为什么我们需要在这里执行while {...} while(0)循环?我们试图告诉编译器一些东西吗?
例如,在Linux内核2.6.25中,包含/ asm-ia64/system.h
/*
* - clearing psr.i is implicitly serialized (visible by next insn)
* - setting psr.i requires data serialization
* - we need a stop-bit before reading PSR because we sometimes
* write a floating-point register right before reading the PSR
* and that writes to PSR.mfl
*/
#define __local_irq_save(x) \
do { \
ia64_stop(); \
(x) = ia64_getreg(_IA64_REG_PSR); \
ia64_stop(); \
ia64_rsm(IA64_PSR_I); \
} while (0)
Run Code Online (Sandbox Code Playgroud)
Ore*_*ost 25
它总是在宏中使用,因此在调用后需要分号,就像调用常规函数一样.
在你的例子中,你必须写
__local_irq_save(1);
Run Code Online (Sandbox Code Playgroud)
而
__local_irq_save(1)
Run Code Online (Sandbox Code Playgroud)
会导致错误的分号错误.如果不在那里,那就不会发生这种情况.如果它只是一个范围,一个简单的大括号对就足够了.
Joh*_*itb 24
它允许代码显示在这里:
if(a) __local_irq_save(x); else ...;
// -> if(a) do { .. } while(0); else ...;
Run Code Online (Sandbox Code Playgroud)
如果他们只是使用了{ .. }你会得到的
if(a) { ... }; else ...;
Run Code Online (Sandbox Code Playgroud)
else不再属于任何一个if,因为分号将是下一个语句并将其else与前一个分开if.将发生编译错误.
AnT*_*AnT 11
do{ ... } while(0)构造的目的是将一组语句转换为可以用a终止;的单个复合语句.你会看到,在C语言中,do/while构造有一个奇怪的和不寻常的属性:即使它"作为"复合语句,它;最终会有一个.C中没有其他复合结构具有此属性.
由于这个属性,你可以do/while用来编写多语句宏,它可以安全地用作"普通"函数而不用担心宏内部的内容,如下例所示
if (/* some condition */)
__local_irq_save(x); /* <- we can safely put `;` here */
else
/* whatever */;
Run Code Online (Sandbox Code Playgroud)
答案已经给出了(因此宏强制;调用时),但是我已经看到过这种语句的另一种用法:它允许在"循环"中的任何地方调用break,如果需要则提前终止.基本上是你的同事程序员不会谋杀你的"goto".
do {
int i = do_something();
if(i == 0) { break; } // Skips the remainder of the logic
do_something_else();
} while(0);
Run Code Online (Sandbox Code Playgroud)
请注意,这仍然相当混乱,所以我不鼓励使用它.
| 归档时间: |
|
| 查看次数: |
6026 次 |
| 最近记录: |