Macro definition?

I ran across this macro definition in code for AFSK modulation/demodulation (microAPRS) and can't think of a good reason for the "do {" and "} while(0)" bits. I would just leave them out. Anyone?

#define LED_TX_ON()   do { LED_PORT |= _BV(1); } while (0)

I would leave it out. It has no effect.

Regards, Ray L.

Google "C macro do while".

Good explanation here

(AWOL already answered while I was typing this, but I am not going to throw this into the bit recycler...)

There are cases where leaving them out will result in an error:

#define FOO() {...}  

if (...) FOO();
else ...;

This expands to

if (...) {...};  // empty statement between {} and ;
else ...;        // disconnected else without a matching if

With do {...} while (0) you get valid code

if (...) do {...} while (0);   
else ...;

If you always use braces with if/else, you will not have this problem.

RayLivingston: I would leave it out. It has no effect.

AWOL is right. It has a syntactical effect. Very important depending on the circumstances.

Of course this:

#define FOO() {...}  

if (...) FOO()
else ...;

would work just fine...

And it seems unlikely anyone would use the macro in question in a context where not having the do/while would cause a problem, since it does nothing but set a register bit.

Regards, Ray L.

RayLivingston: Of course this:

#define FOO() {...}  

if (...) FOO() else ...;




would work just fine...

And it seems unlikely anyone would use the macro in question in a context where not having the do/while would cause a problem, since it does nothing but set a register bit.

Regards,
Ray L.

But the more natural

#define FOO() {...}  

if (...) FOO();
else ...;

would fail

AWOL: But the more natural

#define FOO() {...}  

if (...) FOO(); else ...;


would fail

That may be "more natural" for some, but it is the CAUSE of the whole problem. I've been programming in c since the late '70s, and my habit has always been to NOT put a semi-colon after a macro. If one is needed, I include it in the macro. I've used an awful lot of muti-line macros under all kinds of conditions, and in all these years, and countless lines of code, I've never once run into this "problem". Seems like a lot of bother just to put in a superfluous semi-colon...

Regards, Ray L.

How do you know it's a macro? For example:

#define interrupts() sei()
#define noInterrupts() cli()

Did you know they are macros?

[quote author=Nick Gammon link=msg=2655023 date=1457552342] How do you know it's a macro? For example:

#define interrupts() sei()
#define noInterrupts() cli()

Did you know they are macros? [/quote]

Seriously??? Well, let's see. If it's a macro I wrote myself, I'll know, because I wrote it.. If it's not something I wrote myself, I'd assume if it looks like a function, then it's a function. That one time in a million where I'm wrong, and it matters, I'll get a compiler error, which will point out my error, and I'll add or remove the semi-colon as necessary. How many macros have you seen that use that do/while trick? I could count them on the fingers of one hand, and have several fingers left over.

Regards, Ray L.

How many macros have you seen that use that do/while trick?

Dozens of them in the Linux kernel. Well, there were back when I was doing a port of some file systems and RAID drivers from 2.4 to 2.6.

RayLivingston:
How many macros have you seen that use that do/while trick?

It’s very common. Looking at the Arduino install directory, for example:

find . -type f -iname '*.h' -exec grep -inPH --color "while ?\(0\)"  {} \;

Just a sample:

./hardware/mighty-1284p-1.6.3/avr/bootloaders/optiboot/boot.h:798:} while (0)
./hardware/mighty-1284p-1.6.3/avr/bootloaders/optiboot/boot.h:810:} while (0)
./hardware/mighty-1284p-1.6.3/avr/bootloaders/optiboot/boot.h:822:} while (0)
./hardware/mighty-1284p-1.6.3/avr/bootloaders/optiboot/boot.h:834:} while (0)
./hardware/mighty-1284p-1.6.3/avr/bootloaders/optiboot/boot.h:846:} while (0)

Piping to “wc” to get the total:

   689    2698   60291

One example from power.h:

#define power_all_enable() \
do { \
    PR_PRGEN &= (uint8_t)~(PR_AES_bm|PR_EBI_bm|PR_RTC_bm|PR_EVSYS_bm|PR_DMA_bm|PR_USB_bm); \
    PR_PRPA &= (uint8_t)~(PR_DAC_bm|PR_ADC_bm|PR_AC_bm); \
    PR_PRPB &= (uint8_t)~(PR_DAC_bm|PR_ADC_bm|PR_AC_bm); \
    PR_PRPC &= (uint8_t)~(PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm); \
    PR_PRPD &= (uint8_t)~(PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm); \
    PR_PRPE &= (uint8_t)~(PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm); \
    PR_PRPF &= (uint8_t)~(PR_TWI_bm|PR_USART1_bm|PR_USART0_bm|PR_SPI_bm|PR_HIRES_bm|PR_TC1_bm|PR_TC0_bm); \
} while(0)

So, 689 times in the Arduino install alone (I didn’t check if every “while (0)” was done for that reason, but why else would they have it?).

I wasn't aware of this semicolon deal. I confess the depth of my ignorance is such that I only use some macros, never make any. But, to RayL's comment, isn't an awareness of whether something is a macro or a function, kind of good thing to know when you use it? Surely it has ramifications beyond just whether it contains a semicolon?

What is the best way to do a multi-statement macro?

http://c-faq.com/cpp/multistmt.html

Generally it does not matter. It used to be the only way to inline functions. One major difference is that you can easily make type agnostic macros.