[GCC] itoa()-Derivate

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[GCC] itoa()-Derivate

Beitrag von Krishty »

Hi,

Kann mir jemand, der mit GCC Erfahrung hat, sagen, was die C-Runtime für Funktionen anbietet, um Ganz- und Gleitkommazahlen in Strings zu schreiben? Ich finde im Netz nur ominöse Hinweise, dass es mit 3.4 noch einfach so ging oder dass man sowas gar selber schreiben sollte …

… also, direkte Funktionen für Zahlen mit acht bis 64 Bits in statische Puffer zur Basis zehn und 16. Keine printf()- oder stringstream-Derivate, die ja entweder keine 64-Bit-Ganzzahlen oder andere Basen als zehn unterstützen, dynamischen Speicher allokieren oder saulangsam sind – eben die Gegenstücke zu _ultoa_s(), _itoa_s(), _ui64toa_s(), _i64toa_s() und _gcvt_s() aus Visual C++’ C-Runtime.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Sternmull
Establishment
Beiträge: 264
Registriert: 27.04.2007, 00:30
Echter Name: Til
Wohnort: Dresden

Re: [GCC] itoa()-Derivate

Beitrag von Sternmull »

Eine fertige Lösung hab ich nicht parat. Für Integer ist eine eigene Implementierung aber schnell gemacht. Für Gleitkommazahlen würde ich mir das allerdings nicht zutrauen. Vor Kurzem hatte ich mal gesucht was es da Fertiges gibt und hab mir letzten Endes diese Implementierung hier vorgemerkt. Die gute Nachricht: Die Lizenz ist brauchbar. Die schlechte Nachricht: Ich habs bisher selber nicht ausprobiert und weiss nicht ob der Code brauchbar ist. Besteht aus Unmengen #if #endif. Ich hoffe mal das man die Allkationen auf alloca umbiegen kann. Bin an Erfahrungsberichten oder einer besseren Möglichkeit interessiert :)

Mich hat primär die Locale-Abhängigkeit der Standardfunktionen motiviert mich nach Alternativen umzusehen. Außerdem ging es mir in erster Linie um die andere Richtung. Dazu findet sich z.B. hier eine brauchbare Lösung (die allerdings Integer Overflows ignoriert!). Möglicherweise hast du dafür ja in dem zusammenhang auch Verwendung.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

Toll.

Das kann doch nicht sein, dass eine Laufzeitbibliothek so was Grundlegendes nicht zur Verfügung stellt?! Womit arbeiten denn deren ::sprintf() und ::std::ostream intern?!
Ich kriege schon wieder so eine Wut auf die GCC-Ecke …

Aber danke für die Links – wenn es hart auf hart kommt, implementiere ich das echt wie in den Links.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [GCC] itoa()-Derivate

Beitrag von eXile »

Krishty hat geschrieben:Das kann doch nicht sein, dass eine Laufzeitbibliothek so was Grundlegendes nicht zur Verfügung stellt?! Womit arbeiten denn deren ::sprintf() und ::std::ostream intern?!
Ich kriege schon wieder so eine Wut auf die GCC-Ecke …
So wie ich grade durch den Code gestapft bin, würde ich sagen, die GNU libc benutzt die GNU libio dafür. Hier die entsprechende Funktion, die dabei die ganze Arbeit macht (für sprintf würde für fp ein String-File übergeben werden, also wundere dich nicht darüber, dass die zusammenarbeiten können). Am interessantesten müsste für dich dann __cvt_double sein, weil das in einen hinreichend großen Speicherbereich genau den übergebenen double-Wert dort als String reinschreibt.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [GCC] itoa()-Derivate

Beitrag von BeRsErKeR »

strtol (String -> long)
strtoul (String -> unsigned long)
strtod (String -> double)

Hat mich ca 2 Sekunden in der C-Library Doku gekostet.
Ohne Input kein Output.
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: [GCC] itoa()-Derivate

Beitrag von eXile »

Um deine Euphorie zu bremsen:
Krishty hat geschrieben:... um Ganz- und Gleitkommazahlen in Strings zu schreiben
Und es geht vor allen Dingen darum, dass man das in einen statisch allokierten String fester Größe schreiben will, da ja die maximale float- oder double-Stringrepräsentation eine fixe Länge besitzt.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

eXile hat geschrieben:So wie ich grade durch den Code gestapft bin, würde ich sagen, die GNU libc benutzt die GNU libio dafür. Hier die entsprechende Funktion, die dabei die ganze Arbeit macht (für sprintf würde für fp ein String-File übergeben werden, also wundere dich nicht darüber, dass die zusammenarbeiten können). Am interessantesten müsste für dich dann __cvt_double sein, weil das in einen hinreichend großen Speicherbereich genau den übergebenen double-Wert dort als String reinschreibt.
Achtung, Anfängerfrage: Ich habe auf meinem Windows Code::Blocks mit MinGW installiert. Welche C-Laufzeitbibliothek wird GCC nun linken? Ich kann nämlich nirgends in meiner Installation eine Datei finden, die auf „libc“ schließen würde, geschweige denn eine Referenz zu __cvt_double() :(

Vorerst habe ich überall snprintf() hingehauen. Unter GCC steht mir dank C99 ja immerhin das ll-Postfix zur Verfügung, um 64-Bit-Zahlen ausgeben zu können … das klappt logischerweise nur im C++0x-Modus, aber ich werde immer unsicherer, ob ich C++98 bei dem ganzen Geraffel überhaupt noch weiter unterstützen will.

@BeRsErKeR: Ja, es geht mir genau um die andere Richtung.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von kimmi »

Wie wäre es mit depends? Da sollte doch die Runtime-Dll, sofern als Dll vorhanden, in der Dependency-Liste angezeigt werden.

Gruß Kimmi
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Aramis »

Das kann doch nicht sein, dass eine Laufzeitbibliothek so was Grundlegendes nicht zur Verfügung stellt?! […]
Ich kriege schon wieder so eine Wut auf die GCC-Ecke …
Ich wuerde an deiner Stelle meine Wut lieber gegen das Standard-Komitee richten. „Die GCC-Ecke” macht es im Grunde genommen richtig, davon abgesehen dass sie nicht alles symetrisch zur MSVC-Implementierung aufziehen. Aber das will man ihnen ja nicht vorwerfen, oder? :-)
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

Klar, in erster Linie geht die Wut gegen das Standardkommittee. Aber ganz in Unschuld kann sich GCC die Hände auch nicht waschen -- die round()- und trunc()-Funktionen stellen sie sogar im ANSI-only-Modus zur Verfügung, obwohl sie nicht Teil des Standards sind, und weigern sich, sie wieder rauszunehmen. Diese Bigotterie hat mich vor laaaanger Zeit, als ich von GCC auf Visual C++ umgestiegen bin (kaum zu glauben, aber angefangen habe ich vor tausend Jahren auf GCC) schon Haare gekostet ... quasi selbe Sache wie heute: Ich war schockiert, dass mir so grundlegende Funktionen nicht zur Verfügung gestellt werden.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [GCC] itoa()-Derivate

Beitrag von BeRsErKeR »

eXile hat geschrieben:Um deine Euphorie zu bremsen:
Krishty hat geschrieben:... um Ganz- und Gleitkommazahlen in Strings zu schreiben
Und es geht vor allen Dingen darum, dass man das in einen statisch allokierten String fester Größe schreiben will, da ja die maximale float- oder double-Stringrepräsentation eine fixe Länge besitzt.
Ups da hab ich mich wohl verlesen.


@Krishty: Mal ehrlich, wozu brauch ich itoa wenn es sprintf oder stringstreams gibt. Das bischen an Overhead wird man heutzutage wohl verkraften können. sprintf kann auch 64Bit-Werte und die Basen 10 und 16. stringstreams können auch die beiden Basen, ob 64Bit-Werte, weiß ich grad nicht. Ich habe itoa noch nie gebraucht und es auch ehrlich gesagt nicht vermisst.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

BeRsErKeR hat geschrieben:@Krishty: Mal ehrlich, wozu brauch ich itoa wenn es sprintf oder stringstreams gibt. Das bischen an Overhead wird man heutzutage wohl verkraften können. sprintf kann auch 64Bit-Werte und die Basen 10 und 16. stringstreams können auch die beiden Basen, ob 64Bit-Werte, weiß ich grad nicht. Ich habe itoa noch nie gebraucht und es auch ehrlich gesagt nicht vermisst.
Ja, sprintf() ist eine Möglichkeit, wenn auch eine für meinen Geschmack etwas zu Schwere. Benutze ich jetzt ja auch – aber 64-Bit-Ganzzahlen gehen eben nur unter C99 und C++0x. Gegen stringstream spricht, dass ich keinen Speicher allokieren darf und der Overhead gemessen an der Aufgabe wirklich zu groß ist.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [GCC] itoa()-Derivate

Beitrag von BeRsErKeR »

Hab nen lustigen Code dazu gefunden und ihn ein wenig erweitert:

Code: Alles auswählen

char* itoa(int value, char* str, int base, int size)
{
    if(!value)
    {
        str[0] = '0';
        str[1] = '\0';
        return str;
    }

    static char buf[32] = {0};
    bool sign = value < 0;

    if(sign)
        value = -value;

    int i = std::min(size, 31);

    for(; value && i; value /= base)
        buf[--i] = "0123456789abcdef"[value % base];

    if(sign && i)
        buf[--i] = '-';

    memcpy(str, &buf[i], std::min(size, 32-i));

    return str;
}
Aufruf dann z.B. so:

Code: Alles auswählen

char str[20];
itoa(500, str, 10, 20);
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

Ja – lustig ist vor allem das Verhalten, wenn der kleinste negative Wert übergeben wird (im Zweierkomplement ist eine negative Zahl mehr darstellbar als Positive, value = -value bleibt negativ und damit ist "0123456789abcdef"[value % base]; undefiniert. Also wird es im besten Fall vom Optimizer durch = 0 ersetzt, im Schlimmsten stürzt es zur Laufzeit ab).

Außerdem sorgt das static vor dem Puffer dafür, dass der Puffer nur beim ersten Mal mit 0 initialisiert wird und bei späteren Aufrufen die Reste der vorherigen Zahlen in der Ausgabe landen, wenn man dabei die Puffergröße verringert.

Ich wette, da stecken noch zwei oder drei weitere solcher Dinger drin, die hier keinem von uns auffallen, bevor es nicht knallt. Und genau deshalb will ich es nicht selber schreiben, sondern – wie im Fall von Microsofts Laufzeitbibliothek – bis zum Erbrechen getestete, bewährte, verifizierte, vorgefertigte Funktionen.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [GCC] itoa()-Derivate

Beitrag von BeRsErKeR »

Soweit ich gesehen habe wird das bei so ziemlich jeder itoa-Implementierung mit value = -value gemacht. Wäre ja mal interessant das bei der Visual Studio Implementierung zu testen.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

Funktioniert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4886
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas
Wohnort: Dresden
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Schrompf »

Das Beispiel knallt außerdem im Multithreaded-Betrieb, weil die Funktion ohne Not mit einem static buffer arbeitet. Wenn man eh einen Zielspeicher angeben muss und selbst dafür sorgen muss, dass er groß genug ist - warum dann der Umweg über den internen Zwischenpuffer?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: [GCC] itoa()-Derivate

Beitrag von BeRsErKeR »

Wie gesagt, das Beispiel sollte nicht als Lösung dienen. Ich fand die Implementierung optisch nur sehr amüsant. Der static buffer ist meiner Meinung nach deshalb vorhanden, weil der erzeugte String in der Regel kürzer ist als die Größe des Buffers und man in dem Fall nicht die Startaddresse des Buffers zurückgibt. Das Verfahren baut den String ja von hinten nach vorn auf und daher wären sonst die vorderen Zeichen leer bzw mit unnötigem Inhalt belegt. Klar wäre schon deshalb ein Verfahren besser, welches den String von vorn nach hinten aufbaut. Ich glaube in der Regel wird ein string-reverse ausgeführt nachdem die Zahl in umgedrehter Ziffernreihenfolge in den Buffer gelegt wurde.
Ohne Input kein Output.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [GCC] itoa()-Derivate

Beitrag von Krishty »

BeRsErKeR hat geschrieben:Das Verfahren baut den String ja von hinten nach vorn auf und daher wären sonst die vorderen Zeichen leer bzw mit unnötigem Inhalt belegt. Klar wäre schon deshalb ein Verfahren besser, welches den String von vorn nach hinten aufbaut. Ich glaube in der Regel wird ein string-reverse ausgeführt nachdem die Zahl in umgedrehter Ziffernreihenfolge in den Buffer gelegt wurde.
Ja, ein Reversal macht Microsofts Implementierung auch. Rein vom Konzept her habe ich auch nichts gegen einen funktionsinternen Puffer … hier glaube ich aber eher, dass jemand die Bedeutung von static nicht verstanden hat.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten