Forum: Compiler & IDEs Stringformatierung Codegrösse


von Manfred H. (mhelectronics)


Lesenswert?

Hallo Leute,

für die Ausgabe eines float Wertes auf ein LCD wollte ich ursprünglich 
die dtostrf-Funktion nutzen. Die braucht aber allein schon ca. 4kB = 50% 
des flash auf dem Atmega88 !
Zur Abhilfe dann habe ich den float Wert mit 10 multipliziert und in int 
gewandelt, diesen Wert dann mit der itoa-Funktion  zum String gemacht. 
Soweit OK, Codegrösse im Rahmen.
Jetzt möchte ich diesen String noch rechtsbündig formatieren und ein 
Komma vor der letzten Ziffer einfügen (= int-Wert/10). Dazu brauche ich 
die String-Länge. Die eingebaute strlen-Funktion braucht aber ebenfalls 
ca. 3kB = 35% meines Flash. Deshalb habe ich eine eigene Funktion 
geschrieben:

int string_length(char *c, int max_string_size)
  {
  //int i = 0;
  //while(c[i] ; && i < string_size);
  //return i;

  for(int i=0; i < max_string_size; i++)
    if (!c[i])
    return i;

  return 0;
  }

Diese Funktion braucht ebenfalls ca. 3kB ! Egal ob als while- oder 
for-Schleife ! Die weitere Untersuchung ergab daß der große 
Codeverbrauch einzig aus der Zeile " if (!c[i]) " herrührt. Sobald ich 
diese auskommentiere oder in z.B "if (i>5)" ändere brauche ich 3kB 
weniger.
Das Array besteht aus max. 5 Ziffern. Eingebunden sind nur <avr/io.h> 
und <stdlib.h>.

Kann mir jemand sagen warum diese simple Abfrage soviel code verbraucht 
oder wie ich den float Wert (ca. -100.0 bis +300.0) sparsamer in einen 
rechtsbündigen String wandeln kann.

Gruß Manfred

von Falk B. (falk)


Lesenswert?

Vergiss Float. Nimm Festkommaarithmetik.

von Johannes M. (johnny-m)


Lesenswert?

Manfred Häfner wrote:
> Hallo Leute,
>
> für die Ausgabe eines float Wertes auf ein LCD wollte ich ursprünglich
> die dtostrf-Funktion nutzen. Die braucht aber allein schon ca. 4kB = 50%
> des flash auf dem Atmega88 !
Du solltest vielleicht, wenn Du schon absolut nicht auf floats 
verzichten kannst, die Linkeroption -lm hinzufügen.

Für die meisten Fälle in der Praxis sind Gleitkommaberechnungen aber 
tatsächlich überflüssig!

> int string_length(char *c, int max_string_size)
>   {
>   //int i = 0;
>   //while(c[i] ; && i < string_size);
>   //return i;
>
>   for(int i=0; i < max_string_size; i++)
>     if (!c[i])
>     return i;
>
>   return 0;
>   }
>
> Diese Funktion braucht ebenfalls ca. 3kB !
Diese Funktion braucht, so wie sie hier steht, nie im Leben 3 KiB!

von SoLaLa (Gast)


Lesenswert?

hmmm...
wenn das c[i] und string_length sonst nirgendwo benutzt wird, dann 
optimiert der Compiler doch bestimmt die ganze Bibliothek weg

von Karl H. (kbuchegg)


Lesenswert?

Johannes M. wrote:

>> Diese Funktion braucht ebenfalls ca. 3kB !
> Diese Funktion braucht, so wie sie hier steht, nie im Leben 3 KiB!

Genauso wie ich nicht glaube, dass die Original strlen 3 KiB verbraucht. 
Da ist irgendetwas anderes faul. Irgendwas kann wegoptimiert werden, 
wenn der Vergleich rausfällt. Und als Folge davon werden wiederrum 
andere Teile wegoptimiert, sodass unterm Strich ein Wenigerverbrauch von 
3KB rauskommt.

von Peter D. (peda)


Lesenswert?

Johannes M. wrote:
> Diese Funktion braucht, so wie sie hier steht, nie im Leben 3 KiB!

Warscheinlich wieder ein Fall für den "-lm" Superman.

Hast Du nicht auch 264 Byte SRAM verloren?


Peter

von Manfred H. (mhelectronics)


Lesenswert?

Danke für den schnellen Feedback .....

1. Die Funktion verbraucht nicht 256 Byte SRAM, nur etwa 7-10 Byte, 
entsprechend der Stringlänge.

2. ist die Funktion so wie beschrieben, belegt das gesamte Programm im 
flash ca. 4.3 kB, nach deaktivieren nur der Zeile " if (!c[i]) " nur 
noch ca. 1.2 kB. Das Abscannen des nur ca. 6 Felder langen array belegt 
also eindeutig ca. 3 kB im flash. (mit mehreren Optimierungsgraden 
getestet, Unterschiede nur unwesentlich!). Bei Verwendung der 
strlen-funktion dasselbe.

3. Das array c[i] wird natürlich bei der itoa() funktion beschrieben und 
bei der LCD ausgabe mit lcd_string() gelesen, sonst wird es nirgends 
benutzt, die string_lenght() wird sonst nicht benutzt.

4. Festkommaarithmetik wende ich schon an, hat mit der sting_length() 
nix zu tun. Der Umbau des Programms von float zu int hat zuvor etwa 800 
byte gebracht.

5. wo muß die linker-option " -lm " hin? in das makefile oder? (bin 
Anfänger mit GCC :-).
Nutzt es was, wenn ich den gesamten Code mal hier anhänge?

Gruß Manfred

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Das Abscannen des nur ca. 6 Felder langen array belegt
> also eindeutig ca. 3 kB im flash.
Ich denke eher, der Compiler sieht, dass immer der gleiche Wert
zurückgegeben wird, und kann was anderes rausschmeißen.
Schau doch mal das Assembler-File an, dort siehst du, wer dir den 
Speicher verbrät.

> Nutzt es was, wenn ich den gesamten Code mal hier anhänge?
Ja.
Als Dateianhang mit der Endung .c, dann wird er hübsch formatiert ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.