Comparing two preprocessor macros

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

#if DEV_PORT == PORTB
#define PCI PCIE0
#define PCMSK PCMSK0
#define PCINT_VECT PCINT0_vect

#elif DEV_PORT == PORTC
#define PCI PCIE1
#define PCMSK PCMSK1
#define PCINT_VECT PCINT1_vect

#else
#define PCI PCIE2
#define PCMSK PCMSK2
#define PCINT_VECT PCINT2_vect
#endif

compiler says:

operator '*' has no left operand

How should I check which port is the DEV_PORT in compile time? MCU is ATmega328P.

Slow and Steady!

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

pajuhesh80 wrote:

compiler says:

operator '*' has no left operand

Where, exactly, does it say that?

 

The best way to see what's going on when you get problems with preprocessor macros is to look at the preprocessor output.

 

With GCC, use -save-temps:

 

https://gcc.gnu.org/onlinedocs/gcc/Developer-Options.html - search on that page for "save-temps"

 

from 2002: http://www.8052mcu.com/forum/rea...

 


BTW: rather than just an 'else' at the end of your test, I would strongly recommend that you have an "error catch":

#define DEV_PORT PORTC

#if DEV_PORT == PORTB
#define PCI PCIE0
#define PCMSK PCMSK0
#define PCINT_VECT PCINT0_vect

#elif DEV_PORT == PORTC
#define PCI PCIE1
#define PCMSK PCMSK1
#define PCINT_VECT PCINT1_vect

#elif DEV_PORT == PORTE
#define PCI PCIE2
#define PCMSK PCMSK2
#define PCINT_VECT PCINT2_vect

#else 
#error Unsupported DEV_PORT
#endif

Then you won't get invalid DEV_PORT settings being defaulted to PORTE

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sat. Feb 13, 2021 - 02:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The #if preprocessor conditional  will be flummoxed by

the definition of PORTB being something like (*(volatile uint8_t *)((0x05) + 0x20))

 

First thing that springs to mind is you could do something like the following (there may be other/better ways)

#define DEV_PORT_SELECT_PORTB 1
#define DEV_PORT_SELECT_PORTC 2
#define DEV_PORT_SELECT_PORTD 3

/* choose one of the above */
#define DEV_PORT_SELECT DEV_PORT_SELECT_PORTB

#if DEV_PORT_SELECT == DEV_PORT_SELECT_PORTB
#define DEV_PORT PORTB
/* other stuff */
#elif DEV_PORT_SELECT == DEV_PORT_SELECT_PORTC
#define DEV_PORT PORTC
/* other stuff */
#elif DEV_PORT_SELECT == DEV_PORT_SELECT_PORTD
#define DEV_PORT PORTD
/* other stuff */
#else
#error "DEV_PORT_SELECT not set"
#endif

int main(void)
{
    DEV_PORT = 0xff;
}

 

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

#define DEV_PORTC 

 

#if defined(DEV_PORTB)

#define DEV_PORT PORTB
//...

 

#elif defined(DEV_PORTC)
#define DEV_PORT PORTC
//...

 

#elif defined(DEV_PORTD)
#define DEV_PORT PORTD
//...

 

#else
#error "DEV_PORT not defined"
#endif

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

awneil wrote:
I would strongly recommend that you have an "error catch":

I was thinking about it also, but I should get it to work first. Thanks for this suggestion.

 

MrKendo wrote:

the definition of PORTB being something like (*(volatile uint8_t *)((0x05) + 0x20))

First thing that springs to mind is you could do something like the following  (there may be other/better ways)

Your solution is good but isn't there any straight way to check if two macros are same?

Slow and Steady!

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

pajuhesh80 wrote:
isn't there any straight way to check if two macros are same?

Not really.

 

You need to understand how macros work: the comparison is done after the macros have been expanded.

 

What  MrKendo  suggested is a pretty standard approach:

 

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

 

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

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pajuhesh80 wrote:
How should I check which port is the DEV_PORT in compile time?

 

Not really possible, as mentioned. Compile time is really 2 steps:

1) preprocess step

2) actual compile step

 

What you are asking is if you can compare macros at the preprocess step. Not that I know of, only numeric expressions. You can expand the macros and stringify them, then compare/process the strings at the compile step if you are using C++ (i.e. with constexpr functions).

This is an extremely convoluted process that I tried once just as proof of concept, not something I recommend.

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

You have to bear in mind that the preprocessor doesn't know anything about keywords, types, pointers, enumerations etc.

Those things are only understood by the compiler.

So given

#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))

if you say

#if PORTB

when the preprocessor evauluates that #if expression it doesn't apply any special meaning to volatile and uint8_t,  it just sees volatile as an undefined macro and substitutes 0, likewise uint8_t,

so it actually sees

#if (*(0 0 *)((0x05) + 0x20))

 

That's why, for example, you can't use  a cast in a preprocessor #if expression (eg. it would choke on #if (uint16_t)33 ), and you can't use sizeof() etc.

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

Silly question but have you considered C++ rather than C? Templates allow you to achieve a lot of what you might previously have done with preprocessor macros in C but are done by the compiler not in a separate parsing phase.

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

isn't there any straight way to check if two macros are same?

Not really.

 

I think Only if they are purely numeric expressions. :-(

 

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

Silly question but have you considered C++ rather than C? Templates allow you to achieve a lot of what you might previously have done with preprocessor macros in C but are done by the compiler not in a separate parsing phase.

I dislike defines/macros as much as anyone, but the wrench in the gears for any of this is the ISR. The easy part is setting up the pcint, and can be easily done in any language without defines but you are still left with what to do about the isr, and will be doing something less than ideal no matter what language.

 

https://godbolt.org/z/cW8T5K

(notice lack of defines, and using C)

 

The original #if method is fine (and probably easiest/best) until you want to also use another pcint. Now what to do. Then you probably do something like the above which uses functions, and you also get all the vectors in use which is harmless and the unused code optimizes away (bare/minimal vector code remains when isr not used).

 

 

Last Edited: Sat. Feb 13, 2021 - 10:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are writing the problem macro yourself,

the answer is to improve your organization.

#define the answers to the desired questions.

Use conditionals to select #define-s for others.

 

If you are low on control, another technique if to make guesses.

Write some code that will fail to compile if you guess wrong.

Moderation in all things. -- ancient proverb