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?

2
  • 2
    Your interpretation is not accurate. Nov 8, 2017 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, 2017 at 19:54

2 Answers 2

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!

4
  • How can you customize optimization with Arduino IDE/UECIDE?
    – user31481
    Nov 8, 2017 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. Nov 8, 2017 at 20:47
  • Such innocent OP's question and what valuable answers.
    – user31481
    Nov 8, 2017 at 21:14
  • 1
    @LookAlterno I went digging for iron and found gold Nov 8, 2017 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.

5
  • So const uint8_t will be also automatically be stored in flash? Nov 8, 2017 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. Nov 8, 2017 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. Nov 8, 2017 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, 2017 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, 2017 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.