Ab welcher Stringlänge macht das F-Makro Sinn ?

Hallo,

ich wollte ein Programm mit diversen Ausgaben auf einem 20x4 I2C Display nun so umschreiben, daß alle Strings via dem F() Makro RAM-sparend ausgegeben werden.

Ich frage mich, ab welcher Stringlänge das eigentlich Sinn macht, da ein Unterprogrammaufruf wie das F-Makro doch auch RAM braucht (Ablage der Adresse auf dem Stack etc.) ?!

Spare ich nun wirklich RAM, wenn ich sehr kurze Ausgaben wie
lcd.print(F("A:")); schreibe, statt lcd.print("A:"); ?

Bei lcd.print(F("Das ist echt lang")); verstehe ich das ja.

Gruß,

Tütenflieger

Tütenflieger:
Spare ich nun wirklich RAM, wenn ich sehr kurze Ausgaben wie
lcd.print(F("A:")); schreibe, statt lcd.print("A:"); ?

Ja.

Du magst zwar "auf dem Stack" mehr RAM-Verbrauchen, wenn Du komplexere Funktionen mit längeren Parametern aufrufst. Aber dieser zusätzliche "RAM-Bedarf auf dem Stack" entsteht nur während die Funktion läuft. Sobald der Funktionsaufruf beendet ist, wird das RAM auf dem Stack nicht mehr benötigt und ist wieder frei. Zum Beispiel für den nächsten Funktionsaufruf.

Aber wenn Du lcd.print("A:"); schreibst, dann sind die drei Bytes des Strings dauerhaft im RAM belegt, während der gesamten Laufzeit des Programms.

Wenn also lcd.print("A:"); der absolut einzige Funktionsaufruf mit Ausgabe eines so kurzen Strings ist, mag das F-Makro tatsächlich kontraproduktiv für den RAM-Verbrauch sein. Aber wenn Du im Programm viele ähnliche Aufrufe hast, kannst Du eine Menge RAM durch Gebrauch des F-Makros einsparen.

Allerdings ist das F-Makro kontraproduktiv für die Programmgröße: Je öfter Du das F-Makro einsetzt, desto mehr wächst die Programmgröße.

jurs:
Allerdings ist das F-Makro kontraproduktiv für die Programmgröße: Je öfter Du das F-Makro einsetzt, desto mehr wächst die Programmgröße.

Liegen konstante Strings nicht sowieso im Flash, und werden erst beim Start/Reset ins Ram kopiert?
Von daher sollte der Fash zuwachs sich in Grenzen halten.
ungetestet (aber das mache ich mal!)

Und wenn alle Stricke reißen, gibts ja immer noch das EEPROM

Hier mal mein Testcode:

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

void loop() 
{
 Serial.print(F("a"));
 Serial.print(F("b"));
 Serial.print(("c"));
 Serial.print(("d"));
 Serial.print(("e"));
 Serial.print(("f"));
 Serial.print(F("g"));
}

Getestet auf einem UNO und IDE 1.5.5 r2

Versehe ich keine Ausgabe mit einem F ist der Flashbedarf 1794

Sobald ich auch nur ein F setze steigt der Bedarf auf 1864.
Und dann ist es auch egal wie viele (bis 6) F man setzt.

Wenn alle Ausgaben mit F versehen werden sinkt es auf 1802

Also:
Wenn ein F kompiliert wird, kostet es 70 Byte. Alle weiteren sind egal.
Packt man konsequent alle Strings ins Flash hat man nur einen Mehrbedarf von 8 Byte im Flash, unabhängig von der Anzahl.

Witzig, damit hätte ich jetzt auch nicht in der Form gerechnet.

Ich vermute, das bei der Verwendung von F eine weitere Funktion mit hineingebunden wird.
Und das beim Verzicht auf Strings im Ram die (Reset)Kopierfunktion weg optimiert wird.

F() ist ein Makro, aber das verwendet eine kleine FlashStringHelper Klasse. Der String wird ist das normale PSTR(str) gehüllt (also nichts anderes als das PROGMEM) und dann auf diese Klasse gecastet.

Das wird gemacht damit der Compiler beim Funktionsaufruf einen normalen String und einen Flash String unterscheiden kann. Sonst wäre das nicht möglich, da mit PROGMEM beide const char* sind.

Packt man konsequent alle Strings ins Flash hat man nur einen Mehrbedarf von 8 Byte im Flash, unabhängig von der Anzahl.

Witzig, damit hätte ich jetzt auch nicht in der Form gerechnet.

Woher die 8 Byte kommen, weiss ich auch nicht, aber jeder string im RAM muss natürlich auch einen Initialwert im Flash haben.

Wenn alle Ausgaben mit F versehen werden sinkt es auf 1802

Wenn du nirgends print(char*) verwendest, sondern immer nur print(FlashStringHelper*), kannst du ein bisschen Code sparen.

Also Danke für die ganzen Antworten.
Da ich durchaus mehrere kleine Ausgaben der Art lcd.print("P:"), lcd.print("I:") etc. habe, werde ich den F() Makro wohl wirklich überall einsetzen.

Gruß,

Tütenflieger

Bei einzelnen Zeichen ist es besser gar keine Strings zu verwenden. Also nicht

lcd.print("a")

sondern

lcd.print('a').

Weiterhin ist es so, daß das F Makro sich keine Strings merkt. Falls der gleiche String mehrfach ausgegeben werden soll kann man also noch mehr rausholen wenn man die Aufrufe sinnvoll in Unterprogramme packt. Das rentiert sich aber erst wenn auch der Flash Speicher knapp wird.