#define problem .. I lost my mind!

Hi, sorry for my bad English

I wrote code that has millis() function to repeat some code frequently, I wrote this:

#define OFFTIMERs 50
.
.
if (millis() - millisLow >= (OFFTIMERs * 1000)) {
..
}

when I use "#define" it didn't work, I replaced it with "static word" and it worked perfectly..
Can you explain why this happened ??

thank you

Let's not wonder to much about what 'didn't work' means,
#define create a literal, but on an AVR architecture a literal is considered a signed 16-bit integer (which for 50 would be OK) and therefore the calculation is done as such. The maximum value then would be 32767, yours rolls over.
try

#define OFFTIMERs 50UL

or

if (millis() - millisLow >= (1000UL * OFFTIMERs ))

To define 1 of the values as a an Unsigned Long, so the result will also be an 'unsigned long'

1 Like

seems to work fine for me. comparison between long and int doesn't seem to matter because the subtraction between the long is in the range of an int (< 65535)

0
5000
10000
15000
20000
25000
30000
35000
40000
45000
50000
55000
60000
65000
70000
75000
80000
85000
90000
95000
100000
105000
110000
115000
120000
125000
130000
135000
140000
145000

#define OFFTIMERs 5

unsigned long millisLow;

// -----------------------------------------------------------------------------
void loop ()
{
    if (millis() - millisLow >= (OFFTIMERs * 1000)) {
         Serial.println (millisLow);
         millisLow = millis ();
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

}

Exceptionally useful information :+1:

There's almost never a good reason to define a constant with a preprocessor macro. Much better to take advantage of the far more intelligent compiler and it error / type checking:

const uint32_t offTimerS = 50;
1 Like

Agreed, but almost is not never, and understanding the interaction between the preprocessor and the compiler is valuable information.

A color library, for instance is a perfectly acceptable use of preprocessor constants as it only includes used colors in your final code.

1 Like

The complier will surely optimize out any unused variables ('const' or otherwise). Thus, they won't be included in the final code either.

I'm going to drop this discussion as semantic and off-topic.

But that doesn't answer the OP's question at all.

Relevant is that in a math operation. (OFFTIMERs * 1000)
The operation will be done and the result will be stored as a (temporary) variable of the size of the biggest size variable of the operands, in this case both values are considered signed 16-bit integers (them being literals), and so if the result is bigger than 32767 (which it is in the original code) the variable will overflow.

Just as an afterthought, one can re-define a preprocessor macro, but one can not re-define a constant variable.

1 Like

That always makes me smile

1 Like

Like jumbo shrimp?

Oh that's good, the world needs more smiles. And to think that my afterthought was going to give reason for discussion.

My understanding is that #define is a leftover from C, and using a const is the better way.
const unsigned long OFFTIMERs=50;
or
constexpr unsigned long OFFTIMERs=50;

#define is sloppy as the compiler does a blind replacement at compile time regardless of context. It can cause some very difficult problems to diagnose.

Define and other preprocessor directives are not leftovers, they are necessary holdovers. OP's use is not really the best idea but they are used correctly in many other areas, this includes the Arduino core stuff. Some pin assignment functions are actually preprocessor directives.

Define is not sloppy, but this application of it is.

Or it is just by habit. I got my mind around the idea that C lets one shoot towards the feet and often hit them doing, and I've not really taken up many new ideas to keep from that.

I'm fired!

a7

C - Preprocessors (tutorialspoint.com)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.