Strange behavior with #define constant

Started by Uncle Buzz, November 29, 2019, 08:44:24 AM

Uncle Buzz

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...

#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 :
QuoteFLASHSECTOR = 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

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

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 !