在浏览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需要"无操作语句".但为什么这种特殊的呢?特别是,空括号,虚假条件,做......而?一些语法警告我无法理解?
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.谢谢!