#define foo()的目的是做{}而(0)

SF.*_*SF. 22 c loops

在浏览LinCAN驱动程序的源代码时,我发现了一些困扰我的宏.

#else /*CONFIG_PREEMPT*/
#define can_preempt_disable()      do { } while (0)
#define can_preempt_enable()       do { } while (0)
#endif /*CONFIG_PREEMPT*/
Run Code Online (Sandbox Code Playgroud)

我理解的有用性

do { 
  ...;
  if(condition) break;
  ... 
} while (0); 
Run Code Online (Sandbox Code Playgroud)

使用break作为一种throw.我半理解包装一系列函数,如

#define FOO() do { foo(); bar(); } while (0)
Run Code Online (Sandbox Code Playgroud)

避免使用无支撑的警告if.我理解有时#define需要"无操作语句".但为什么这种特殊的呢?特别是,空括号,虚假条件,做......而?一些语法警告我无法理解?

ple*_*siv 23

这是一种通用语法,用于通知编译器应将宏视为语句而不是表达式(语句与表达式).

在这种情况下,如果您尝试can_preempt_disable()用作表达式,编译器将提醒您.这意味着我们强制编译时检查can_preempt_disable()用作语句.编译时检查通常是可取的.

  • `(void)0`将达到防止表达式值被使用的目标. (2认同)

unw*_*ind 17

相关文件完整段落是:

#if !defined(CONFIG_PREEMPT_RT) && ( defined(CONFIG_PREEMPT) ||
    (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) )
#define can_preempt_disable preempt_disable
#define can_preempt_enable preempt_enable
#else /*CONFIG_PREEMPT*/
#define can_preempt_disable() do { } while (0)
#define can_preempt_enable() do { } while (0)
#endif /*CONFIG_PREEMPT*/ 
Run Code Online (Sandbox Code Playgroud)

因此,第一部分是您在请求抢先保护时获得的代码,否则您将获得空的,无操作的循环.

我猜他们的写法是出于通常的原因,即确保宏仍然是一个有效的语句.

定义中不应该有一个终止分号,因为它将在使用这些的代码中,例如此函数开始:

int c_can_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
{
    can_preempt_disable(); 

    ...
Run Code Online (Sandbox Code Playgroud)

所以,很明显,宏像任何其他函数调用一样使用,分号就在那里调用宏.这很正常.

更新2:将它定义为;导致双分号,这是丑陋的,至少在我看来.一个空的一对括号{}将工作我猜,但是这do/while因为它在这样的情况下经常使用的结构是更地道.

更新3:正如评论中所指出的,空支撑对不起作用,因为在调用之后你不能放一个分号.AAH.谢谢!

  • @SE如果你做了`#define can_preempt_disable(); `那么`if(foo())can_preempt_disable(); else bar();` - >`if(foo());; else bar();`这是一个语法错误.如果你将它定义为空,`#define can_preempt_disable()`,那么`while(foo())can_preempt_disable();` - >`while(foo());`会产生至少一些编译器的警告(例如clang),你可以在你不应该使用的地方使用can_preempt_disable(),例如`for(; can_preempt_disable();)` (8认同)
  • "一个空的支撑对{}我会猜测" - 不,它不会......"if(x)can_preempt_disable(); 别的......`不会编译.`do {} while(0)`的重要特征是它没有被终止. (2认同)