1

Just discovered this. When I cast an int to a char inside a Serial.print statement it costs way less program memory. I'm not sure why. Could someone explain this to me? In the following example the difference is 228 bytes!

Serial.print(1); // 1676 bytes program storage space. 184 bytes of dynamic memory.
Serial.print((char) (48 + 1)); // 1448 bytes program storage space. 184 bytes of dynamic memory.

EDIT: Adding from different comments:

Serial.print('1'); // Sketch uses 1448 bytes program memory, 184 bytes dynamic memory
Serial.write(48 + 1); // Sketch uses 1448 bytes program memory, 184 bytes dynamic memory

EDIT: For an int > 9, adding quotes in following example saves 218 bytes program memory but adds 4 bytes to dynamic memory usage.

Serial.print(123); // 1676/184 bytes
Serial.print("123"); // 1458/188 bytes
Serial.print(String(123)); // 2772/194 bytes

EDIT2: Max digits in Arduino-uno int is 5(?). You save 80 bytes by converting it to a char array, in comparison to just printing the integer:

Serial.print(12345); // 1676/184 bytes
char digits[5];
int number = 12345;
for (int i = 4; i >= 0; i--) {
  digits[i] = (number %10) + 48;
  number /= 10; 
}
Serial.print(digits); // 1596/184 bytes

To test for yourself, uncommenting one or the other:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print(1); // uses 1676/184 bytes
  //. Serial.print((char) (48 + 1)); // uses 1448/184 bytes
  //  Serial.print('1'); // uses 1448/184 bytes
  //  Serial.write(48 + 1); // 1448/184 bytes
  //  Serial.print(123); // 1676/184 bytes
  //  Serial.print("123"); // 1458/188 bytes
  //  Serial.print(String(123)); // 2772/194 bytes
  //  Serial.print(12345); // 1676/184 bytes | 1676/184
  //  Serial.print("12345"); // 1458/188 bytes | 1460/190
  //  char buff[5];
  //  itoa(12345, buff, 10);
  //  Serial.print(buff); // 1604/184 bytes
  char digits[5];
  int number = 12345;
  for (int i = 4; i >= 0; i--) {
    digits[i] = (number %10) + 48;
    number /= 10;
  }
  Serial.print(digits); // 1596/184 bytes
}
void loop() {
  // put your main code here, to run repeatedly:

}

EDIT: Second question: Shouldn't this be optimised somehow? Or should I always take care of this myself? And why/how? ;)

*the chars 0-9 have a decimal value of 48-57 in the Ascii table, hence (char)(48 + 0-9) prints 0-9

2
  • 1
    short answer: it is not the same print function. you could try .print('1') and .print((char) 1) too
    – Juraj
    Oct 11, 2022 at 17:50
  • 1
    @Juraj You are right, I tested always printing an integer in combination with above examples. And the the memory usage evens out at some point. I guess the compiler optimises the int print function out if you only ever print chars/strings. And vice versa. Which it would when they invoke different functions.
    – Gaai
    Oct 12, 2022 at 15:00

1 Answer 1

3

The difference is simply this:

  • Print this character

and

  • Interpret this integer as a sequence of digits, work out the ASCII characters that represent each digit in turn, and print them.

As you can see even just writing out what the second one does takes more words. Printing an integer is a lot more work than just printing one character. Think about what it takes to print the value 2034578 and how you would do that given that you can only output individual numbers 0-9 and the data isn't stored as the numbers 0-9 but a series of just 0 and 1...

It takes work. Lots of work.

11
  • So why not cast it to a char in the background then. As that takes less work, lots of less work ;)
    – Gaai
    Oct 11, 2022 at 14:42
  • 2
    @Gaai, because that is not what the int overload of .print() does in the general case. You cannot print .print(123); correctly with a single cast and addition. You're invoking the machinery that allows for correct printing of 123 even if you only ask for 1, and so you pay for that. The answer is correct.
    – timemage
    Oct 11, 2022 at 14:54
  • print is a convinience function for easily printing different types as ASCII text. If all you want is to print a single character, then you shouldn't use print, but write. You yourself have to chosse the correct tool for your work
    – chrisl
    Oct 11, 2022 at 15:01
  • @chrisl Ah yes. This makes sense. That should be added to the answer! Serial.write(1) costs the same as the single char print.
    – Gaai
    Oct 11, 2022 at 15:09
  • 1
    @Gaai The first bullet point "print this character" is the single character that you are opn about.
    – Majenko
    Oct 11, 2022 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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