1

I'm taking a course on Arduino Uno programming and on today's talk I heard that the const data is optimized by Arduino, so that it occupies less space than the actual data type (namely, a const int occupies less than an int).

If instead of int I use const uint8_t, const uint16_t etc. is the optimization still applied, or does using the 8 and 16 bit ints represent bad practice?

  • 1
    Your interpretation is not accurate. – Ignacio Vazquez-Abrams Nov 8 '17 at 19:47
  • I guess your teacher is talking about RAM vs PROGMEM, two separate space address. If you put string constants in PROGMEM you are saving RAM. – user31481 Nov 8 '17 at 19:54
4

This question is not really about the Arduino. It is about GNU C/C++ compiler optimizations.

By adding the keyword const the compiler can do a lot of optimization. One is that the value does not need to be stored in SRAM. The value can end up as part of an instruction, become part of an expression that is evaluated at compile-time, etc.

In the Arduino-GPIO library static const member data is used to allow the compiler to optimize to a single instruction digitalRead() with almost X100 performance improvement (on Arduino Mega).

Check GCC and AVR optimizations for further details.

  1. http://www.nongnu.org/avr-libc/user-manual/using_tools.html
  2. https://gcc.gnu.org/wiki/avr-gcc
  3. http://www.linuxjournal.com/article/7269

Cheers!

  • How can you customize optimization with Arduino IDE/UECIDE? – user31481 Nov 8 '17 at 20:42
  • 1
    You can write code in such a way that the compiler can use further optimizations. You can also use compiler options to tell the compiler to "try harder". The IDE gets the compiler options from the platform.txt file. See "compiler.c.flags" etc. – Mikael Patel Nov 8 '17 at 20:47
  • Such innocent OP's question and what valuable answers. – user31481 Nov 8 '17 at 21:14
  • 1
    @LookAlterno I went digging for iron and found gold – theSongbird Nov 8 '17 at 21:19
1

Const memory will still store ts value both in Flash and in SRAM. For arrays PROGMEM can be used and for strings F() to remove the copy to SRAM.

Normal (non const) memory will be stored in SRAM. And if it is initialized with a value, that value is stored in Flash.

However, uint8_t will always occupy 1 byte, and uint16_t always two bytes.

You can read more about the different types of memory and F here.

You can read more about program here.

Update:

Test with const:

const uint8_t  Amount1 = 4;
const uint8_t  Amount2 = 4;
const uint8_t  Amount3 = 4;
const uint8_t  Amount4 = 4;
const uint8_t  Amount5 = 4;
const uint8_t  Amount6 = 4;
const uint8_t  Amount7 = 4;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print(Amount1);
  Serial.print(Amount2);
  Serial.print(Amount3);
  Serial.print(Amount4);
  Serial.print(Amount5);
  Serial.print(Amount6);
  Serial.print(Amount7);
}

Result: 1758 bytes of program storage space, 184 bytes of dynamic memory.

Same without word 'const:

Result: 1758 bytes of program storage space, 184 bytes of dynamic memory. No difference

using #define Amount1..7 4

Result: 1702 bytes of program storage space, 184 bytes of dynamic memory.

Conclusion: to save Flash space, use #define instead of (const) uint8_t. However, also see Jot's experiment, it seems that code optimalization is smarter than my conclusion.

  • So const uint8_t will be also automatically be stored in flash? – theSongbird Nov 8 '17 at 21:17
  • I updated my answer, it seems there is no difference between using const or not, to save space for simple variables #define should be used. – Michel Keijzers Nov 8 '17 at 21:56
  • 1
    The difference you see is probably due to #define loosing the type information: you are calling a different print() method. When AmountX is typed as uint8_t, you are calling Print::print(unsigned char, int). When you #define it with no explicit type, you are calling Print::print(int, int). It is not a general rule that #define saves flash, and loosing the type information is generally considered a misfeature. – Edgar Bonet Nov 8 '17 at 22:18
  • 1
    Such a simplistic experiment can't show you what is really going on. The compiler will be optimizing out all those variables (if they even exist they will just be in registers, not RAM) - chances are it will just optimize them out to the literals since nothing else is being done with the variables. Optimization is very much a black box and can scupper any attempts to second guess it. – Majenko Nov 8 '17 at 23:23
  • 1
    MichelKeijzers and @Majenko I did a few tests, and the 184 bytes means that the const data does not use any sram memory. The compiler optimizes it out of the sram memory. When I put it in sram, the sram size becomes 192. The code size can be reduced with a for loop. With a for loop, the const array makes the sram size 192, because that is indeed copied from flash to sram as you wrote. However, you underestimated the optimization of the compiler. This is for the AVR chips only, because they can not read data from flash memory (a function is needed for that). – Jot Nov 9 '17 at 1:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.