Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of #define foo() do { } while (0)

Tags:

While browsing sources of LinCAN driver, I found some macros that baffled me.

#else /*CONFIG_PREEMPT*/
#define can_preempt_disable()      do { } while (0)
#define can_preempt_enable()       do { } while (0)
#endif /*CONFIG_PREEMPT*/

I understand the usefulness of

do { 
  ...;
  if(condition) break;
  ... 
} while (0); 

using break as a kind of throw. I semi-understand wrapping a sequence of functions like

#define FOO() do { foo(); bar(); } while (0)

to avoid caveats with braceless if. I understand sometimes "no-op statements" are required for a #define. But why this particular kind? specifically, empty braces, false condition, do...while? Some syntax caveats I can't quite grasp?

like image 945
SF. Avatar asked Oct 07 '14 11:10

SF.


People also ask

What is its purpose meaning?

the reason for which something exists or is done, made, used, etc. an intended or desired result; end; aim; goal.

What is an example of purpose?

Purpose is defined as to plan or intend to do something. An example of purpose is someone deciding they will start saving 10% of their income. An object to be reached; a target; an aim; a goal. A result that is desired; an intention.

Is it the purpose for or the purpose of?

The "purpose of" a shoe is protecting your feet. A possible "purpose for" a shoe is to smash bugs. So "purpose of" describes a property or capacity of a shoe, where "purpose for" describes what might be done with a shoe.

How do you use purpose?

How to use Purpose in a sentence. His purpose for bringing her here was unclear. If you win or lose, let it be on purpose. That served another purpose when the conversation turned to the possibility of another child.


2 Answers

It is a common syntax for notifying the compiler that macro should be treated as a statement instead of as an expression (statements vs expressions).

In this case compiler will alert you if you try to use can_preempt_disable() as an expression. This means that we forced compile-time check that can_preempt_disable() is used as a statement. Compile-time checks are very often desirable.

like image 85
plesiv Avatar answered Oct 14 '22 08:10

plesiv


The complete passage from the relevant file is:

#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*/ 

Thus, the first part is the code you get when you've asked for pre-emption protection, otherwise you get the empty, do-nothing, loops.

I guess they're written like that for the usual reasons, i.e. to ensure that the macro still is a valid statement.

There shouldn't be a terminating semicolon in the definition, since that will be in the code using these, such as this function which begins:

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

    ...

So, clearly the macro is used like any other function call, and the semicolon is right there where the macro is invoked. This is very normal.

UPDATE 2: Defining it to a ; leads to double semicolons which is ugly, at least in my opinion. An empty brace pair {} would work I guess, but this do/while construct is even more idiomatic since it's often used in cases like these.

UPDATE 3: As pointed out in a comment, an empty brace pair won't work since then you can't put a semicolon after the call. Aah. Thanks!

like image 31
unwind Avatar answered Oct 14 '22 10:10

unwind