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
Pete K. schrieb:> Hallo,>> ich habe ein Problem, dass das Fromatieren von einer float Variablen> nicht funktioniert.>> Die Zuweisung lautet:>
1
>charbuffer[50];
2
>floatf_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:
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)
Dirk B. schrieb:> (seit C11 ist aber auch %lf gültig. Wohl aus Resignation)
Nicht ganz.
Es vereinfacht die Verwaltung von Format Strings, wenn man die zb aus
Datenbanken zulädt. Dann benötigt man keine Unterscheidung, ob der
Formatstring für printf oder für scanf benutzt werden soll.
Dirk B. schrieb:> 1. Werden bei Funktionen mit variabler Argumentenliste (dazu gehört auch> printf) float als double übergeben.
Richtig.
Der Cast ist trotzdem weder notwendig noch sinnvoll, da sorgt der
Compiler schon selbst dafür.
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
inlinevoidprintInt32(int32x){printf("%i",x);}
2
inlinevoidprintFloat(floatx){printf("%i",x);}
3
inlinevoidprintString(charx[]){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...)
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)
>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)
:-)
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.
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
>inlinevoidprintInt32(int32x){printf("%i",x);}
2
>inlinevoidprintFloat(floatx){printf("%i",x);}
3
>inlinevoidprintString(charx[]){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
(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.
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 ;-)