sprintf mit float Frage

#3990765
Lesenswert?

Hallo,

ich habe ein Problem, dass das Fromatieren von einer float Variablen 
nicht funktioniert.

Die Zuweisung lautet:
1
char buffer[50];
2
float f_ftun;
3

4
sprintf(buffer, "Mhz=%f  ",(double)f_ftun);

Ausgabe: Mhz=?

Libraries sind wie folgt im AVRStudio4.18 gesetzt:
libprintf_flt.a
libm.a
libc.a
libscanf_flt.a


Ausgabe Build:
avr-gcc -mmcu=atmega328p  rda5708m.o twimaster.o uart.o RDA5708M_lib.o 
-lprintf_flt -lm -lc -lscanf_flt  -o rda5708m.elf

Irgendetwas habe ich vergessen, oder?
#3990796
Lesenswert?

Hmm, geht immer noch nicht:

avr-gcc  -mmcu=atmega328p -gdwarf-2 -std=gnu99 -Wall   -Wl,-u,vfprintf 
-lprintf_flt -Wl,-u,vfscanf -lscanf_flt    -lm   -DF_CPU=8000000UL -Os 
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums 
-Wl,-u,vfprintf  -Wl,-u,vfscanf  -MD -MP -MT RDA5708M_lib.o -MF 
dep/RDA5708M_lib.o.d  -c  ../RDA5708M_lib.c

avr-gcc -mmcu=atmega328p  rda5708m.o twimaster.o uart.o RDA5708M_lib.o 
-lprintf_flt -lm -lc -lscanf_flt  -o rda5708m.elf
#3990873
Lesenswert?

Pete K. schrieb:
> Sorry, AVRStudio ist 4.19 Build 730 mit AVR-Toolchain. Macht das einen
> Unterschied?

Ich hab jetzt die Reihenfolge nicht analysiert, in der die Argumente in 
deinem gcc Aufruf auftauchen, aber die Reihenfolge ist da wichtig.

Halte dich an diese Vorgehensweise
http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_bei_WinAVR_bzw_AVR-Studio
und du kriegst das richtige Ergebnis
#3990988
Lesenswert?

Pete K. schrieb:
> Hmm, geht immer noch nicht:
>
> avr-gcc  -mmcu=atmega328p -gdwarf-2 -std=gnu99 -Wall   -Wl,-u,vfprintf
> -lprintf_flt -Wl,-u,vfscanf -lscanf_flt    -lm   -DF_CPU=8000000UL -Os
> -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
> -Wl,-u,vfprintf  -Wl,-u,vfscanf  -MD -MP -MT RDA5708M_lib.o -MF
> dep/RDA5708M_lib.o.d  -c  ../RDA5708M_lib.c

Die "-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt    -lm"

sind IMO Optionen für den Linker und nicht für den Compiler.

Folglich gehören sie unten rein:

> avr-gcc -mmcu=atmega328p  rda5708m.o twimaster.o uart.o RDA5708M_lib.o
> -lprintf_flt -lm -lc -lscanf_flt  -o rda5708m.elf
#3999115
Lesenswert?

Pete K. schrieb:
> Hallo,
>
> ich habe ein Problem, dass das Fromatieren von einer float Variablen
> nicht funktioniert.
>
> Die Zuweisung lautet:
>
1
> char buffer[50];
2
> float f_ftun;
3
> 
4
> sprintf(buffer, "Mhz=%f  ",(double)f_ftun);
5
>
>
> Ausgabe: Mhz=?

Warum wird f_ftun nach double gecastet? (Für double bräuchtest du %lf 
im Formatstring statt %f)
Und welcher Wert hat f_ftun? (Im obigen Code-Schnipsel ist das 
undefiniert)

Was passiert wenn du den Code wie folgt änderst:
1
char buffer[50];
2
float f_ftun = 3.14;
3
 
4
sprintf(buffer, "Mhz=%f  ", f_ftun);
#3999246
Lesenswert?

Eric B. schrieb:
> Für double bräuchtest du %lf
> im Formatstring statt %f)

Das ist Unfug.

1. Werden bei Funktionen mit variabler Argumentenliste (dazu gehört auch 
printf) float als double übergeben.
2. Ergibt sich daraus, dass %f sowohl für double als auch float gilt.
(seit C11 ist aber auch %lf gültig. Wohl aus Resignation)

Beachte, dass die 2. Aussage nur für die printf-Familie gilt.
(scanf ist eine ganz andere Funktion. Da werden Pointer übergeben)
Gast #4008474
Lesenswert?

Ich komme zwar aus der C Welt, aber ich habe nie verstanden, warum alle 
Welt mit (s)printf arbeitet. Eine der häufigsten Probleme mit Ausgabe 
von Daten liegt an den (s)printf Formatierstrings...
Einmal in C++ mit Typsicheren Streams gearbeitet und ich wollte nie mehr 
zurück (musste es aber, weil C im embedded halt nicht tot zu kriegen 
ist...)

Ein Kollege hat es so gelöst, er hat sich einzelne Aufrufe gebastelt:
(aus dem Gedächtnis...)
1
inline void printInt32(int32 x) {printf("%i",x);}
2
inline void printFloat(float x) {printf("%i",x);}
3
inline void printString(char x[]) {printf("%i",x);}

Ist am Anfang gewöhnungsbedürftig, aber jetzt meckert der Compiler, wenn 
man den falschen Typ nutzt.

Wenn's der C Compiler kann wäre jetzt natürlich Polymorphie das Mittel 
der Wahl:
(aus dem Gedächtnis...)
1
inline void print(int32 x) {printf("%i",x);}
2
inline void print(float x) {printf("%i",x);}
3
inline void print(char x[]) {printf("%i",x);}
#4008555
Lesenswert?

Micca schrieb:
> aber ich habe nie verstanden, warum alle
> Welt mit (s)printf arbeitet.

Weil es in C nichts anderes gibt.
(und weil die Formatierung bei cout umständlich ist.)

Micca schrieb:
> aber jetzt meckert der Compiler, wenn
> man den falschen Typ nutzt.
Der Compiler meckert auch bei printf. Allerdings als Warnung, wenn man 
sie aktiviert.
Wenn man weiß was man tut, ist C ok. (aber wer weiß das schon)
Gast #4008715
Lesenswert?

>Der Compiler meckert auch bei printf. Allerdings als Warnung, wenn man
sie aktiviert.
Korrekt. Inzischen können viele Toolchains Warnings werfen.
Aber ich seh das so: jetzt habe ich eine streng typisierte Sprache und 
entdecke den Fehler erst zur Laufzeit.

>Weil es in C nichts anderes gibt
Jepp, die Std Libs geben nichts her. Hinzu kommt, dass printf nicht 
gerade wenig Speicher benötigt.

>Wenn man weiß was man tut, ist C ok. (aber wer weiß das schon)
:-)
Gast #4011667
Lesenswert?

Micca schrieb:
>>Der Compiler meckert auch bei printf. Allerdings als Warnung, wenn man
> sie aktiviert.
> Korrekt. Inzischen können viele Toolchains Warnings werfen.

Und früher haben sie sie einfach nur ausgegeben?

Micca schrieb:
> Wenn's der C Compiler kann wäre jetzt natürlich Polymorphie das Mittel
> der Wahl:
> (aus dem Gedächtnis...)
> inline void print(int32 x) {printf("%i",x);}
> inline void print(float x) {printf("%i",x);}
> inline void print(char x[]) {printf("%i",x);}

Das hat nichts mit Polymorphie zu tun. Das ist einfache 
Funktionsüberladung.
#4011694
Lesenswert?

Micca schrieb:
> Ich komme zwar aus der C Welt, aber ich habe nie verstanden, warum alle
> Welt mit (s)printf arbeitet.

Weil man mit dem Formatstring eine ganze Latte an Formatierproblemen auf 
einfache und auf wenig geschwätzige Art und Weise in den Griff kriegt. 
Versuch mal einen int als Hex-Zahl auszugeben und dabei führende 0-en 
auf 4 hexadezimale Digits zu erhalten. Klar, ist mit den C++ Streams 
machbar, aber dann doch schon sehr geschwätzig.

> Ein Kollege hat es so gelöst, er hat sich einzelne Aufrufe gebastelt:
> (aus dem Gedächtnis...)
>
1
> inline void printInt32(int32 x) {printf("%i",x);}
2
> inline void printFloat(float x) {printf("%i",x);}
3
> inline void printString(char x[]) {printf("%i",x);}
4
>

in dem Fall ist er aber eine Pfeife. Was bringt ihm hier ein printf im 
Vergleich zu zb einem itoa-puts Gespann? Richtig. Genau gar nichts. Das 
wäre genau so typsicher und hat den ganzen printf Overhead nicht. printf 
bringt dir nur dann was, wenn du die Möglichkeiten des Formatstrings zu 
deinem Vorteil ausnutzen kannst. Leider scheint es so zu sein, dass mehr 
als 60% der 'neuen' C Programmierer gar nicht mehr wissen, was man mit 
dem Formatstring alles anstellen kann und welche Möglichkeiten man da 
hat.

Schreib mal das Äquivalent zu
1
uint8_t hour, minute, second
2
char buffer[10];
3

4
  sprintf( buffer, "%02d:%02d:%02d", hour, minute, second );
5
  lcd_puts( buffer );
(und ja, ich bestehe darauf, dass die Ausgabe nicht an irgendeine 
Konsole geht, sondern auf ein LCD)

Das man bei den Angaben im Formatstring aufpassen muss, ist schon 
richtig. Aber so schlimm ist das jetzt auch wieder nicht, wenn man sich 
daran gewöhnt hat, dass man in der ganzen Programmierung an jeder 
einzelnen Stelle aufpassen und sorgfältig sein muss.
Moderator #4012127
Lesenswert?

Dirk B. schrieb:
> Micca schrieb:
>> aber ich habe nie verstanden, warum alle
>> Welt mit (s)printf arbeitet.
>
> Weil es in C nichts anderes gibt.
> (und weil die Formatierung bei cout umständlich ist.)

Es gibt wohl bisher kein anderes Konzept für die Ausgabeformatierung,
das so leicht und übersichtlich anzuwenden ist (siehe Beispiel von Karl
Heinz). Deswegen haben sehr viele Programmiersprachen (auf Kosten der
Compile-Zeit-Typsicherheit) ein printf- oder sprintf-Äquivalent:

  http://en.wikipedia.org/wiki/Printf_format_string#Programming_languages_with_printf

Auch C#, F#, Visual Basic, Common Lisp und viele weitere Sprachen haben
Formatierungsfunktionen, die nach demselben Prinzip – nur mit einer
anderen Formatsyntax – arbeiten.

Ich selber benutze printf und seine Äquivalent eigentlich auch ganz
gerne (nicht nur in C). Der Wegfall der statischen Typsicherheit ist
zwar unschön, aber auch kein allzu großes Problem, weil nicht zum
Formatstring passende Datentypen in ansonsten statisch typisierten
Sprachen i.Allg. schon beim ersten Probelauf, bei dem das printf in
Aktion tritt, auffallen.


Rolf Magnus schrieb:
> Micca schrieb:
>> Wenn's der C Compiler kann wäre jetzt natürlich Polymorphie das Mittel
>> der Wahl:
>> (aus dem Gedächtnis...)
>> inline void print(int32 x) {printf("%i",x);}
>> inline void print(float x) {printf("%i",x);}
>> inline void print(char x[]) {printf("%i",x);}
>
> Das hat nichts mit Polymorphie zu tun. Das ist einfache
> Funktionsüberladung.

... auch bekannt als Ad-Hoc-Polymorphie ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren