CW 5.9.0 (SE) - Defining an if-else macro in C

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

CW 5.9.0 (SE) - Defining an if-else macro in C

810 Views
AirDragon
Contributor III

Hi all,

 

For my application, I need to do quite a bit of saturation on some data values, so I thought I would be a good idea to turn this:

 

if( x > ceiling)  y = ceiling;else if(x < floor)  y = floor;else  y = x;

 into a #define macro. Problem is, whenever I try to do so, I get at least 2 errors saying that I messed up somewhere.

 

What is the (proper) way of doing this, and is it considered good code practice? (I'd like to not piss off my successor any more than necassary :smileywink: )

Labels (1)
0 Kudos
6 Replies

513 Views
kef
Specialist I

floor() is standard C function from math.h. I would rename it.

Here's your macro.  

#define sat(y, x, flr, ceiling) \   if( (x) > (ceiling) )        \      (y) = (ceiling);          \   else if((x) < (flr))         \      (y) = (flr);              \   else                         \      (y) = (x)

 "\" at line end allows to create multiline macro. Yes, you could write it in one line, but this may be more readable (or not). Never forget to put macro arguments into (), else it may bite you if used with more complex expressions as arguments.

 

Is it good practice? Maybe yes, maybe no. Just look at usage:

   sat(y, y,0,5);
   sat(z,x,0,5);
 

Looking at just these two lines it is not clear what's going on there. Good if you used there for years and know arguments order, or if there's decent comment left at each line. Removing destination argument and reducing arg number to 3 could be easier to remember args order, like sat( x, min, max). But still not perfect thinking about maintenance. Though, you may have different opinion.

Be careful using these macros with different types. Comparing signed type to unsigned, or char to long can be tricky. if/else three isn't much better at mixed types, but at least you will see the code while debugging. Replacing macro with if/elses would take you additional time.. Just IMO, I'm not saying macros don't help

0 Kudos

513 Views
AirDragon
Contributor III

Many thanks kef and bigmac,

 

I had originally wanted to be able to do something like this:

 

    y = sat(x, flr, ceiling);

 

But I found that this wasn't really possible for for a macro, so I tried to go with using the 4 terms.

 

Would an inline function dissemble the same as a macro?  I don't want the MCU to jump to a subroutine every time I need this function...

 

0 Kudos

513 Views
kef
Specialist I

It is possible using conditional assignment operator 

 

#define saturate_x_min_max(x,min,max) \
   ( ((x) > (max)) ? (max) : ( ((x) < (min)) ? (min) : (x)  ) )

 

usage

 

   y = saturate_x_min_max(x, min, max);

 

Regarding inline function. Difference is that macro doesn't care about types you are comparing, while inline function prototype defines argument types. While macro is more flexible (because can be used even with float arguments), it is also more fuzzy. It is fine when all three arguments are of the same type, else either x or min and either x or max will be promoted/typecasted. Side effects are almost guaranteed.

0 Kudos

513 Views
AirDragon
Contributor III

Thanks again kef,

 

I was going over the ISO 9899 PDF last week and did come across the conditional statement. It may not be clear to newcomers, but it does get the job done fairly efficiently.

 

I had originally intended that the min and max values would be #define constants, but I see that in the future they may be declared as variables. I don't think there would be any problems with the min and max as #define's, but there probably would be problems with them as variables.

 

I guess I can make a comment near the macro that addresses this, Lol.

0 Kudos

513 Views
bigmac
Specialist III

Hello,

 

If a particular usage has a degree of consistency for the floor and ceiling values, it may simplify to have these values as additional macros.

 

#define MIN  0#define MAX  5#define sat(y, x)           \   if( (x) > (MAX) )        \      (y) = (MAX);          \   else if((x) < (MIN))     \      (y) = (MIN);          \   else                     \      (y) = (x)

 

Regards,

Mac

 

0 Kudos

513 Views
kef
Specialist I

You can name this macro as saturate_y_x_min_max() to force yourself leaving comment at each line.

0 Kudos