Gegenstück zu atoi/atof
-
Hallo!
Ich möchte aus einem integer/float-Wert einen String generieren.
Beim Suchen bin ich auf ftoa und itoa gestoßen, die (angeblich) in der stdlib sind.
Leider klappt es damit bei mir nicht (ich verwende gcc Version 4.4.7)
Muß ich bestimmte Compileroptionen schalten oder mein gcc aktualisieren?
Oder gibt es noch andere Möglichkeiten?
Ciao
OkkaPapa
-
Nimm doch sprintf.
int a = 17; float b = 35.7; char DummyString[ 255 ]; sprintf( DummyString, "%i %f", a, b );
Ansonsten kannst du dir die Funktionen auch leicht selbst schreiben.
Hier
http://www.mikrocontroller.net/topic/38903
hats einer gemacht.Keine Ahnung ob es ftoa und itoa gibt. Hab ich nie gebraucht und nie gesucht
-
Ich würde lieber snprintf() nehmen. Das verringert die Gefahr von Sicherheitslücken, indem es garantiert, dass wenn ein zu langer String rauskommt, dieser nach einer gewissen Anzahl Zeichen (eben der Größe des Zielstrings, im obigen Beispiel 255) abgeschnitten wird, anstatt über den reservierten Speicherbereich (oben 255 Byte) hinauszuschreiben.
Vermindert zwar minimal die Performance, aber wenn es dir darum geht, wäre selbst schreiben wahrscheinlich eh besser.
-
philipp2100 schrieb:
Ich würde lieber snprintf() nehmen. Das verringert die Gefahr von Sicherheitslücken, indem es garantiert, dass wenn ein zu langer String rauskommt, dieser nach einer gewissen Anzahl Zeichen (eben der Größe des Zielstrings, im obigen Beispiel 255) abgeschnitten wird, anstatt über den reservierten Speicherbereich (oben 255 Byte) hinauszuschreiben.
Vermindert zwar minimal die Performance, aber wenn es dir darum geht, wäre selbst schreiben wahrscheinlich eh besser.
Naja Perfomance hin oder her. Man kann sprintf problemlos verwenden, wenn man vorher beim Programmieren das Gehirn einschaltet. Bei Gleitkommazahlen und Integers kann man sich ungefähr überlegen, wie lang die maximal werden können. Dann dimensioniert man den ZielString entsprechend und fertig.
Das ganze Geheule von "sprintf ist unsicher" ... Keine Ahnung wo das herkommt. "sprintf" ist genauso gut wie alle Funktionen wenn man sie richtig benutzt und genauso scheiße wie die anderen auch, wenn man sie falsch benutzt. Und wenn man eine Funktion falsch benutzt, hat man eben Pech. Aber das kann einem bei anderen Funktionen genauso passieren.
Betrifft im Prinzip alles was "über den Speicher hinaus" schreiben/lesen kann...
memset, memcpy, memmove, strcpy, strncpy -> kann man alles falsch benutzen. Bei snprintf und strncpy kann man übrigens auch die Länge falsch angeben und schwupps wars das
Wer mit C nicht umgehen kann, muss es eben üben und lernen oder zu C++ wechseln
-
itoa und ftoa sind nicht im C Standard enthalten.
Es gibt libcs die diese enthalten, sie machen dasselbe wie die sprintf (s.o. It0101)
siehe dazu auch https://www.mikrocontroller.net/articles/FAQ
-
It0101 schrieb:
philipp2100 schrieb:
Ich würde lieber snprintf() nehmen. Das verringert die Gefahr von Sicherheitslücken, indem es garantiert, dass wenn ein zu langer String rauskommt, dieser nach einer gewissen Anzahl Zeichen (eben der Größe des Zielstrings, im obigen Beispiel 255) abgeschnitten wird, anstatt über den reservierten Speicherbereich (oben 255 Byte) hinauszuschreiben.
Vermindert zwar minimal die Performance, aber wenn es dir darum geht, wäre selbst schreiben wahrscheinlich eh besser.
Naja Perfomance hin oder her. Man kann sprintf problemlos verwenden, wenn man vorher beim Programmieren das Gehirn einschaltet. Bei Gleitkommazahlen und Integers kann man sich ungefähr überlegen, wie lang die maximal werden können. Dann dimensioniert man den ZielString entsprechend und fertig.
Nein, eben nicht! Das ist nämlich implementierungsabhängig. sprintf() ist unsicher!
It0101 schrieb:
Das ganze Geheule von "sprintf ist unsicher" ... Keine Ahnung wo das herkommt. "sprintf" ist genauso gut wie alle Funktionen wenn man sie richtig benutzt und genauso scheiße wie die anderen auch, wenn man sie falsch benutzt. Und wenn man eine Funktion falsch benutzt, hat man eben Pech. Aber das kann einem bei anderen Funktionen genauso passieren.
Aber deutlich weniger leicht wie bei Funktionen wie sprintf(). Aus o.g. Grund ist sprintf() nur sicher, wenn man die maximale Länge in den Format-Spezifier mit einfügt, also bspw. "%11i" statt nur "%i". Die Summe dieser Begrenzer + die konstanten Anteile des Strings dürfen dann die Zielgröße nicht überschreiten. Das ist aber natürlich eine fummligere Angelegenheit als einfach als zusätzlichen Parameter einmal die Länge des Zielstrings zu übergeben (den konstanten Teil noch schnell erweitert - schwupps kann der String zu lang werden). Vor allem aber vergisst man das schnell und schreibt doch mal "%i", ohne dass man dann vom Compiler gewarnt wird. Deshalb bleibts dabei, dass man sich die Verwendung der f..()- und ..n..()-Funktionen angewöhnen sollte, alles andere ist sehr schlechter Stil und führt schnell zu gravierenden Sicherheitslücken.
It0101 schrieb:
Bei snprintf und strncpy kann man übrigens auch die Länge falsch angeben und schwupps wars das
Aber lang nicht so schnell und vor allem kann man das auch gegen Änderungen resistent implementieren. Nur dass man bei dem anderen auch Fehler machen kann, ist doch kein Argument dafür, das inhärent unsichere zu nehmen..
It0101 schrieb:
Wer mit C nicht umgehen kann, muss es eben üben und lernen oder zu C++ wechseln
Sehr richtig! :p Wobei es bei C++ naturgemäßg genau das gleiche Problem gibt beim in char-Arrays lesen.
-
philipp2100 schrieb:
It0101 schrieb:
Wer mit C nicht umgehen kann, muss es eben üben und lernen oder zu C++ wechseln
Sehr richtig! :p Wobei es bei C++ naturgemäßg genau das gleiche Problem gibt beim in char-Arrays lesen.
Daher macht man das in C++ in der Regel auch nicht.
-
philipp2100 schrieb:
Aber lang nicht so schnell und vor allem kann man das auch gegen Änderungen resistent implementieren. Nur dass man bei dem anderen auch Fehler machen kann, ist doch kein Argument dafür, das inhärent unsichere zu nehmen..
Also ich benutze sprintf schon ewig und hatte diesbezüglich noch nie Probleme...
Beim Bund hätte der Truppführer jetzt gefragt: "Was machen Sie richtig, was alle anderen falsch machen"
-
It0101 schrieb:
Beim Bund hätte der Truppführer jetzt gefragt: "Was machen Sie richtig, was alle anderen falsch machen"
"Ich habe vorher nachgedacht."1
1Beim Bund2 wäre das aber die falsche Antwort gewesen.
2wenn du mit Bund die Bundeswehr meinst. Ist aber schon etwas her, dass ich den Verein kennengelernt habe.
-
It0101 schrieb:
Also ich benutze sprintf schon ewig und hatte diesbezüglich noch nie Probleme...
Vermutlich hast du auch noch nie versucht, deine eigenen Programme zu hacken, bzw. solche Randfälle überhaupt getestet.
Und selbst wenn: Implementierungsabhängiges Verhalten auszunutzen und die Komplexität unnötig zu erhöhen ist schlechter Stil & man sollte sich den Umgang mit den sicheren Funktionen angewöhnen.
-
Ach Phillip, wenn du wüsstest, was hier im Forum alles als "schlechter Stil" bezeichnet wird... Wenns nach dem Forum ginge, dürfte ich weder memset, memcpy, memmove, noch überhaupt irgendwelche ANSI-C-Geschichten nutzen.
Vermutlich würde ich dann die Messages für meine Sockets dann mit std::vector<char> oder std::string zusammenbauen...
-
Wenn dir vector<char> empfohlen wird, dann hast du wohl im C++-Forum gefragt und es ist ganz korrekt, dort die memXXX als schlechten Stil zu bezeichnen.
-
Der Punkt ist doch, ob es Sinn macht, eine komplette asynchrone SocketLogik auf vector<char> auszulegen, wenn das Interface ( z.b. winsock ) damit gar nichts anfangen kann... Klar wird jetzt einer sagen: "Dann nimm doch boost::asio", aber letztendlich lügt man sich damit selber in die Tasche.
Wenn man boost-libraries nimmt, die zumindest nach außen ein C++-Interface haben soll das in Ordnung sein, aber wenn man die Socketanbindung selber schreibt mit char * und memXXX ( anders ist das in Boost vermutlich auch nicht gemacht ), dann ist das plötzlich schlechter Stil... Entschuldige bitte, wenn ich das schwachsinnig finde
-
SeppJ schrieb:
Wenn dir vector<char> empfohlen wird, dann hast du wohl im C++-Forum gefragt und es ist ganz korrekt, dort die memXXX als schlechten Stil zu bezeichnen.
... aber m.E. noch im Rahmen, da nicht unmittelbar Security-relevant.
-
It0101 schrieb:
Der Punkt ist doch, ob es Sinn macht, eine komplette asynchrone SocketLogik auf vector<char> auszulegen, wenn das Interface ( z.b. winsock ) damit gar nichts anfangen kann... Klar wird jetzt einer sagen: "Dann nimm doch boost::asio", aber letztendlich lügt man sich damit selber in die Tasche.
Wenn man boost-libraries nimmt, die zumindest nach außen ein C++-Interface haben soll das in Ordnung sein, aber wenn man die Socketanbindung selber schreibt mit char * und memXXX ( anders ist das in Boost vermutlich auch nicht gemacht ), dann ist das plötzlich schlechter Stil... Entschuldige bitte, wenn ich das schwachsinnig finde
Falls sich die Kritik wirklich auf das Vorgehen an sich bezieht, finde ich sie auch ungerechtfertigt, schließlich hat man so einen Performance-Vorteil.
Was SeppJ aber evtl. eher meinte, war das benutzen der memXXX()-Funktionen anstatt z.B. std::copy(). std::copy() ist halt allgemeiner (funktioniert mit allen Iterator-Typen) ohne Geschwindigkeitsnachteil, von daher sollte man sich das schon angewöhnen... Hier schreibt sogar einer, es sei bei ihm schneller:
http://stackoverflow.com/questions/4707012/c-memcpy-vs-stdcopyAber wie gesagt, dafür würde ich dich jetzt nicht steinigen wollen..
-
Ich finde generell, dass viele hier zu dogmatisch unterwegs sind. Erlaubt ist aus meiner Sicht, was in Summe, unter Berücksichtigung aller relevanten Faktoren zum jeweiligen Problem am besten passt.
Faktoren sind:
- korrekte Funktion (!!)
- Wartbarkeit ( da ist C++ meist im Vorteil )
- Performance ( sofern relevant )
- Verständlichkeit / Übersichtlichkeit
- ästhethische Belange ( eher untergeordnet ), ich finde "schönen" Code aber sexyUnd du sagst ja auch selber, dass du bei std::copy im Vergleich zu memcpy "wenigstens keine Performance-Nachteile" in Kauf nehmen musst. Na herzlichen Dank.
Aber gut... die C vs. C++-Diskussion ist so alt, wie C++
-
... wobei für memcpy() spricht, dass hier sehr viel expliziter dargestellt ist, dass es sich eben um einen Kopiervorgang direkt im Speicher handelt und nicht um einen abstrakten mit den Umwegen über die Iteratoren.
-
It0101 schrieb:
Und du sagst ja auch selber, dass du bei std::copy im Vergleich zu memcpy "wenigstens keine Performance-Nachteile" in Kauf nehmen musst. Na herzlichen Dank.
Lies nochmal genauer, von "wenigstens" hab ich nichts gesagt. Im Gegenteil sogar dass es Vorteile hat ohne Nachteile zu haben.
"- Security" fehlt übrigens noch
-
It0101 schrieb:
Der Punkt ist doch, ob es Sinn macht, eine komplette asynchrone SocketLogik auf vector<char> auszulegen, wenn das Interface ( z.b. winsock ) damit gar nichts anfangen kann... Klar wird jetzt einer sagen: "Dann nimm doch boost::asio", aber letztendlich lügt man sich damit selber in die Tasche.
Kommt halt drauf an. Woher nimmst du denn den Pufferspeicher? Wenn du jetzt sagst new/malloc, dann wäre das in C++ einfach nur dumm und umständlich, da es eine kürzere, bessere Lösung (vector<char>) gäbe und du einiges an Verrenkungen machen müsstest, um new/malloc von Hand richtig (richtig != halbwegs richtig) zu benutzen.
Weil ein Interface einen char* verlangt malloc/new zu nehmen, das ist falsch verstanden, was die Bedeutung dieser Datenstruktur ist. Ich vermute aber, das meinst du auch gar nicht, sondern einen festes Array. Da spricht in keiner Sprache etwas gegen und das darfst du auch gerne mit den memXXX-Funktionen behandeln. Das ist ja von der Funktion her gänzlich etwas anderes als vector/new/malloc und dadurch auch nicht ersetzbar. C++-Dogmatiker würden vielleicht ein std::array nehmen. Das kann man sich aber auch sparen, da die ganze Struktur ohnehin in einem struct/class gewrapped sein sollte.
-
Wenn du dein "TicTacToe" codest wird sich keine Sau für Security interessieren. Aber prinzipiell hast du natürlich Recht
Trotzdem finde ich es sehr aussagekräftig wenn "kein Geschwindigkeitsnachteil" jetzt schon als Vorteil von C++ ins Feld geführt wird