Author Topic: Strange behavior with #define constant  (Read 2511 times)

Uncle Buzz

  • Full Member
  • ***
  • Posts: 146
  • Country: fr
Strange behavior with #define constant
« on: November 29, 2019, 08:44:24 AM »
Hi,

I define some constants with #define to reuse many times in my code.

When constant are use directly like pin definition, there is no problem, but if I compute some things with them, results are not what I expected...

Could someone tell me why this occurs? I tried to use some cast but same results...

I put a simple example sketch below, and the result I obtained...

Code: [Select]
#include "arduino.h"

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#define SERIAL_BAUD   115200

#define FLASHSECTOR 1UL<<12 // 4096
#define FLASHPAGE 256

void setup() {
Serial.begin(SERIAL_BAUD);
}

void Blink(byte PIN, int DELAY_MS)
{
pinMode(PIN, OUTPUT);
digitalWrite(PIN,HIGH);
delay(DELAY_MS);
digitalWrite(PIN,LOW);
}

long lastPeriod = 0;
void loop()
{
Serial.print("FLASHSECTOR = ");Serial.println(FLASHSECTOR);
Serial.print("sizeof(FLASHSECTOR) = ");Serial.println(sizeof(FLASHSECTOR));
Serial.print("18 % FLASHSECTOR = ");Serial.println(18 % FLASHSECTOR);
Serial.print("18 % (1UL<<12) = ");Serial.println(18 % (1UL<<12));
Serial.print("FLASHSECTOR * (18 % FLASHSECTOR) = ");Serial.println(FLASHSECTOR * (18 % FLASHSECTOR));
Serial.print("(1UL<<12) * (18 % (1UL<<12)) = ");Serial.println((1UL<<12) * (18 % (1UL<<12)));
Serial.print("0 % FLASHSECTOR = ");Serial.println(0 % FLASHSECTOR);
Serial.print("FLASHSECTOR * (0 % FLASHSECTOR) = ");Serial.println(FLASHSECTOR * (0 % FLASHSECTOR));
Serial.print("FLASHSECTOR * (0 / FLASHSECTOR) = ");Serial.println(FLASHSECTOR * (0 / FLASHSECTOR));
Serial.println();

Serial.print("FLASHPAGE = ");Serial.println(FLASHPAGE);
Serial.print("sizeof(FLASHPAGE) = ");Serial.println(sizeof(FLASHPAGE));
Serial.print("18 % FLASHPAGE = ");Serial.println(18 % FLASHPAGE);
Serial.print("18 % 256 = ");Serial.println(18 % 256);
Serial.print("FLASHPAGE * (18 % FLASHPAGE) = ");Serial.println(FLASHSECTOR * (18 % FLASHPAGE));
Serial.print("256 * (18 % 256) = ");Serial.println(256 * (18 % 256));
Serial.print("0 % FLASHPAGE = ");Serial.println(0 % FLASHPAGE);
Serial.print("0 % 256 = ");Serial.println(0 % 256);
Serial.print("FLASHPAGE * (0 % FLASHPAGE) = ");Serial.println(FLASHSECTOR * (0 % FLASHPAGE));
Serial.print("FLASHPAGE * (0 / FLASHPAGE) = ");Serial.println(FLASHPAGE * (0 / FLASHPAGE));
Serial.println();

Serial.println();
Serial.flush();
delay(1000);

Blink(LED,3);
}

result :
Quote
FLASHSECTOR = 4096
sizeof(FLASHSECTOR) = 4
18 % FLASHSECTOR = 0
18 % (1UL<<12) = 18
FLASHSECTOR * (18 % FLASHSECTOR) = 1
(1UL<<12) * (18 % (1UL<<12)) = 73728
0 % FLASHSECTOR = 0
FLASHSECTOR * (0 % FLASHSECTOR) = 1
FLASHSECTOR * (0 / FLASHSECTOR) = 1

FLASHPAGE = 256
sizeof(FLASHPAGE) = 2
18 % FLASHPAGE = 18
18 % 256 = 18
FLASHPAGE * (18 % FLASHPAGE) = 0
256 * (18 % 256) = 4608
0 % FLASHPAGE = 0
0 % 256 = 0
FLASHPAGE * (0 % FLASHPAGE) = 1
FLASHPAGE * (0 / FLASHPAGE) = 0
(...)

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Strange behavior with #define constant
« Reply #1 on: November 29, 2019, 10:18:34 AM »
It's because of operator precedence.
Modulo (%) is greater than bit shifting (<<) so the compiler result is correct.
The preprocessor simply replaces your define expressions where they are included in your code.

Uncle Buzz

  • Full Member
  • ***
  • Posts: 146
  • Country: fr
Re: Strange behavior with #define constant
« Reply #2 on: November 29, 2019, 10:50:38 AM »
I thought preprocessor replace with the computed value of 4096 instead of keeping 1<<12, but it makes sense...
And some wrong copy/paste did the rest...

Thank you !