1

I'm programming a c++ application on an stm32f4 chip which has several IOs to control. One of my colleagues suggested to make preprocessor statements to all of these IOs to make the code more readable.

For example:

#define FAN_ON     GPIO_SetBits(GPIOD, GPIO_Pin_0);
#define FAN_OFF    GPIO_ResetBits(GPIOD, GPIO_Pin_0);

Is this ok this way, and if not, why? I have not that much microcontroller experience yet, but I read that semicolons shouldn't be used in preprocessor statements and I'm also not sure if it is a good style to use functions in precompiler statements?

Thank you for your help!

lucasg
  • 10,734
  • 4
  • 35
  • 57
  • 1
    It is not about microcontroller programming, it is all about basic `C`. Please have a look on [#define directive in `C`](http://msdn.microsoft.com/en-us/library/teas0593.aspx) – Dayal rai Mar 04 '14 at 14:32
  • IMO, the down side of this is that it makes for much less readable code. – DiBosco Mar 04 '14 at 15:46

2 Answers2

5

It's fine in theory, but you're right in that the semicolons should be avoided.

It's best to wrap the code in a dummy loop:

#define FAN_ON    do { GPIO_SetBits(GPIOD, GPIO_Pin_0); } while(false)

This makes the macro behave like a single statement.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • And now macros are not going to break indentation of your favorite iterator as well! – pmr Mar 04 '14 at 14:33
1

To answer your first question, even though this is common, it is pretty bad style to use preprocessor statements to define functions, except when you really need the preprocessor. You really need the preprocessor when you need things like __LINE__, or preprocessor substitutions tricks like put the function name in a char * variable. You could define a function void fan_on(void) and void fan_off(void) instead of those macros, you can even declare them static inline if you want to declare them in a header like you would do with macros. Functions can be better used by the debugger than macros, and better debugged.

As you said if you still want to use macros you should not use semicolons, and use a do while(0) structure, if you don't using the macro if a single-line if block will only execute the first line of the macro.

Étienne
  • 4,773
  • 2
  • 33
  • 58
  • Thank you, I guess I will do it with inline functions. The only thing I'm not sure is static. If the functions are class methods than it is clear that they have to be static, but if 'fan_off' is a plain C function, I would guess I just have to declare it 'inline', and not 'static inline'? – user3379420 Mar 05 '14 at 12:03
  • In this context static is the opposite of extern, and is not related to C++ classes, it means that the function has internal linkage (i.e. it is only visible in the c file in which it is included). If you don't declare the function static you will have as many definitions of the function as c files using the function which will have external linkage (visible in the whole program), and your linker will complain about multiple definitions. – Étienne Mar 05 '14 at 18:53