Returning a value from a complex function-like macro

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, so I've always wanted to be able to return a value from a complex multi-line macro but have never figured out how to do it.
Ternary is not an option for the kinds of things I'm talking about.

Today I saw some odd looking macro code that was able to perform this magic.

Here is very reduced example of the "magic"
as it can be applied in the AVR world.

#include 

uint8_t var8;

#define avr_rd(type, reg) ({uint8_t f = type ## reg; f;})

void mtest(void)
{
        var8 = avr_rd(PIN, D);
}

The "magic" is the "var;" line.
The original code I saw used "var >>=0;" but
that is essentially the same as this.

My question is why does this work?
Normally the optimizer will remove references to unused rvalues unless they referencing volatile data.
So something like 6; or var; would be totally removed.

So why does this work inside a macro to return the value?

Is this behavior something that is guaranteed to work across all C implementations?

Have I missed out on this known behavior all these years?

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Is this behavior something that is guaranteed to work across all C implementations?
No, this "magic" is a gcc extension. It is described in the documentation in chapter 5.1.

BTW: The PSTR macro in pgmspace.h uses this "magic".

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you so much for the reference.
I guess I need to review section 5.
It has been years since I've looked through the gcc extensions.

That one is extremely useful.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bperrybap wrote:
Ok, so I've always wanted to be able to return a value from a complex multi-line macro but have never figured out how to do it.

inline is defined in C99

static inline uint8_t BetterMacro(uint8_t a, uint8_t b)
{
    ...
}

It will behave the same as a macro as far as code size is concerned.

-- Damien

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Ok, so I've always wanted to be able to return a value from a complex multi-line macro

Why would you think that you could "return" anything from a macro? Macros are text substitution, not functions.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
Ok, so I've always wanted to be able to return a value from a complex multi-line macro

Why would you think that you could "return" anything from a macro? Macros are text substitution, not functions.

Ok, lets not get too hung up on terminology.
Yes, I know getting terminology correct is very important to ensure the correct question is asked to ensure getting the correct answer,
And yes I know that macros are text substitutions, and the real question was related to compound statements
with declarations inside an expression.

Since it was part of a function-like macro it seemed appropriate to simply refer to it as a macro "returning a value".
While technically incorrect, the intent of my question seems to have been understood and already answered.

Damien,
I have used inline functions extensively, however there are some situations
where using function-like macros over inline functions are necessary as they can provide
text mapping capabilities that are lost when the arguments are used as parameters to a function.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bperrybap wrote:

Damien,
I have used inline functions extensively, however there are some situations
where using function-like macros over inline functions are necessary as they can provide
text mapping capabilities that are lost when the arguments are used as parameters to a function.

--- bill

I'm not quite sure what you mean. Can you provide an example?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While very simplistic, consider the original example.
I don't think it is possible to rewrite io_rd() to be a inline function.

This shows an example of situation where strings are passed in as "arguments" and manipulated to form other strings that then are used as part of the final expression.

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Following an example, which can only be done with a macro, but no an inline function.
The reason was, that for every key you need a different variable to held the previous state.

Peter

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  i;				/* return value of Macro */		\

Glad to see I'm not the only one that refers to returning a value from a macro. :D

--- bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Ok, lets not get too hung up on terminology.

If you don't use proper terminology, how can you possibly expect a reasonable answer.
Quote:
Since it was part of a function-like macro it seemed appropriate to simply refer to it as a macro "returning a value".

But the point is that no matter how much it looks like a function, it is not (which is why I never use such a construct).

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define debounce_( port, pin )						\

({									\

  static uint8_t flag = 0;	/* new variable on every macro usage */	\

  uint8_t i = 0;	

The static uint8_t flag is extremely clever. Without the comment, I wouldn't have picked it up.

Nicely done.

-- Damien

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
Ok, lets not get too hung up on terminology.

If you don't use proper terminology, how can you possibly expect a reasonable answer.
Quote:
Since it was part of a function-like macro it seemed appropriate to simply refer to it as a macro "returning a value".

But the point is that no matter how much it looks like a function, it is not (which is why I never use such a construct).
I suppose it's possible that Koschchi wasn't exiled from Lilliput for war crimes,
but I still wouldn't want to eat breakfast with him.

Iluvatar is the better part of Valar.