Arduino Absolute Value: How the Macro/Function Works

Arduino has several mathematical functions, and one of the primary ones is the Arduino absolute value or abs (). But abs works differently when implemented in Arduino vs. in regular C/C++ compilers.  We will explain …

The absolute value in math

Arduino has several mathematical functions, and one of the primary ones is the Arduino absolute value or abs ().

But abs works differently when implemented in Arduino vs. in regular C/C++ compilers. 

We will explain whether Arduino’s absolute value is a function or a macro, how it works, and the issues associated with its use in your code. Read on to learn more!

Table of Contents

What Is Arduino Absolute Value (ABS)?

ABS (Absolute Value) is a function or macro that finds and gives the highest value magnitude of its argument.

In a nutshell, the abs function returns the positive value of the number provided in its parameters.

For instance, the absolute value of -300 is 300, while the abs value of 300 is also 300.

The macro is critical for specific Arduino projects, such as when displaying the speed of a robot.

If you install a directional encoder on one of the wheels, the device will return positive values for forward motion and negative values when reversing.

The -ve data won’t make sense to the user. Picture your car’s speedometer displaying negative values when going in reverse.

A car’s speedometer

A car’s speedometer

With the abs macro, you can rectify this data to show positive values because the negative value only indicates direction. There is no negative speed.

Is ABS a Function or a Macro?

When you Google Arduino ABS, you might get confused about whether it is a macro or a function. The difference is in the implementation language.

ABS is both a function and a macro, but it is a function in C and C++ languages, while in Arduino C/C++, it is a macro.

A function in programming

A function in programming

And in C, the function only works on integer data types. So you will get errors if you give it a float variable as the argument.

But in C++, the function has multiple overloads that enable it to work with other values.

For instance, the abs function is for integers, while float abs (fabs) handles float data types.

There’s also the long abs (labs) function for long and long-long abs (labs) for long-long integers.

Implementation Examples

Consider this example.

int x = -5;

Serial.println(abs(x));

The output will be 5.

But this code will bring an error.

float x = -5.5;

Serial.println(abs(x));

However, this example will work just fine.

float x = -5.5;

Serial.println(fabs(x));

The output will be 5.5.

The Arduino C/C++ language is different from the standard C and C++.

So the abs here is a macro, not a function, and it works for all data types. For instance, consider the following code.

Floax x = -6.2;

Serial.println(abs(x));

The output will be 6.2.

But it is vital to note that this Arduino C/C++ implementation will not work for some microcontroller boards, such as the ESP32, ESP8266, and Arduino Mega. These boards use the standard function implementation and might not work with float values.

Several ESP8266 NodeMCU modules

Several ESP8266 NodeMCU modules

The Issue With ABS Macros

Arduino ABS macros expand code and might not work for each case. Here’s where it works and where it doesn’t.

Where ABS Works Fine

This macro works as expected when dealing with constant values or single-element variables. For instance, a constant like x = abs(-5); will give x = 5, which is correct.

Similarly, working with the absolute value of an integer variable will give an accurate answer. Take a look at this example.

int x = -10;

int y = abs(x);

Serial.println(y);

The output will be 10.

A programmer writing code on a laptop

A programmer writing code on a laptop

The same applies to float variables, such as the following.

float x = -10.81;

float y = abs(x);

Serial.println(y);

The serial monitor output will be 10.81.

Where ABS Fails

But ABS fails when you have multiple operations in the argument. Consider the following code.

int x = -10;

int y = abs(x++);

Serial.println(y);

The result should be 10 because the ++ is a post-increment mathematical operator, but the output will be 9. And when you include this line.

Serial.println(x);

The output will be -8.

From the above, you will note that the macro executes the ++ as a pre-increment operator. Why?

The macro expands into different C-codes, unlike what you’d get when you call a function.

A boy working on an Arduino project with the Arduino IDE open on his laptop

A boy working on an Arduino project with the Arduino IDE open on his laptop

Here’s how the macro works. Its definition is: 

#define abs(x), which translates to ((x) > 0?(x):-(x))

Let’s expand this definition like the compiler.

x = -10 

y = abs(x++) translates to ((-10++)>0?(-10++):-(-10++))

So the variable (x) undergoes two incremental operations, which include the following.

  • The first in the left parenthesis condition
  • Second in the right parenthesis of the selected results

This same issue will occur if you place a function in the macro’s parameters because the macro will call it twice.

Let’s compare it with the abs function. With the same code above, the first output will be 10, and the second -9. Both results are what we expect.

This function has a different definition than the macro, which is:

{return x<0?-x:x;}.

ABS Macro Problems

Arduino C/C++ code will not work in other compilers. Arduino can take the absolute values of floating point numbers in the info file, but other C/C++ compilers will have errors because the standard abs macro version can only handle integers.

A snippet of C code being written in another IDE.

But more importantly, the macro runs the argument twice, resulting in erroneous values. And you will not get any compiler errors because the execution occurs at run time.

Running ABS on Other Compilers

The Arduino IDE scans your code automatically and includes the relevant header files to make the program run. For instance, it adds this line automatically.

#include <stdlib.h>

But other C/C++ compilers are not as intelligent.

So when using regular compilers or those for coding other microcontrollers, you might have to include this header manually.

Wrap Up

In conclusion, Arduino’s absolute value is a macro that can handle multiple data types but only gives the correct output when having constant values and single-element variable arguments. 

However, if you include functions or operations in the parameters, it calls them twice, leading to inaccurate outputs.

On the other hand, abs functions call such arguments only once, resulting in accurate results.

So keep this information in mind if using the macro in your code. 

And contact us if you encounter challenges when using the function.

We’ll help you troubleshoot the issue.