DITTY Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 Hallo COM, System: Linux x64-86 ich probiere mich gerade an einigen Datentypen, u.a. dem GCC bekannten "__int128_t" und "__uint128_t". Übersetzen lassen sich diese und auch das Rechnen funktioniert wunderbar. Ich habe aber gerade ein Problem mit der Ausgabe via printf(,) und std::cout. 1.) printf(,): Ich weiß von anderen Datentypen wie "__int64_t", dass es zumindest für printf(,) spezielle PRI-Makros für solche Datentypen gibt: Galileo Computing :: C von A bis Z – B.7 <inttypes.h> (C99) Folgende Aufrufe funktionieren: printf("x: %"PRIi64"\n",Variable)"; printf("x: %"PRIu64"\n",Variable)"; Doch für die __int128_t-Datentypen irgendwie nicht. Folgendes funktioniert nicht (Compiler-Fehler): printf("x: %"PRIi128"\n",Variable)"; printf("x: %"PRIu128"\n",Variable)"; Compiler-Aufruf: g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s sizeofs_main.cpp -o sizeofs_main Compiler-Output: sizeofs_main.cpp:84: error: expected ‘)’ before ‘PRIu128’ sizeofs_main.cpp:84: warning: spurious trailing ‘%’ in format sizeofs_main.cpp:84: warning: too many arguments for format Da es die beiden Datentypen: __int128_t __uint128_t aber gibt, frage ich mich nun, wie das Makro hierfür heißen muss? 2.) std::cout: Ebenso würde ich gerne wissen, wie ich das mit std:cout ausgeben kann. Mit: __int128_t Var1 = 1024; cout << Var1 << endl; funktionierts zumindest nicht. Compiler-Output: sizeofs_main.cpp:84: error: ambiguous overload for ‘operator<<’ in ‘std::cout << Var31’ /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:165: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:169: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:173: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/ostream.tcc:91: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:180: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/ostream.tcc:105: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:191: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:200: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:204: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:209: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:213: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:221: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:451: note: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char) [with _CharT = char, _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:457: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char) [with _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:463: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char) [with _Traits = std::char_traits<char>] /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../include/c++/4.4.5/ostream:468: note: std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char) [with _Traits = std::char_traits<char>] Bis einschließlich __uint64_t hingegen schon: __uint64_t Var2 = 1024; cout << Var2 << endl; THX schonmal im Voraus! Grüße DITTY :):) Zitieren
i � unicode Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 printf("x: %[COLOR="red"]"[/COLOR]PRIi128[COLOR="red"]"[/COLOR]\n",Variable)[COLOR="red"]"[/COLOR]; Es ist war lange her, dass ich mit C++ gearbeitet habe, aber ich bin mir sicher, dass die printf() so definitiv nicht aufgebaut wird. teste es mal mit: printf("x: %PRIi128\n",Variable); Zitieren
DITTY Geschrieben 11. Oktober 2011 Autor Geschrieben 11. Oktober 2011 Nein nein. Syntax sollte richtig sein. Um ehrlich zu sein, habe ich mich auch über diese Syntax gewundert. Aber hier mal zum Vergleich mit __uint64_t: __uint64_t test = 1024; printf("x: %"PRIu64"\n",Var30); printf("x: %PRIu64\n",Var30); Output - Programm: x: 1024 x: %PRIu64 Wie man sehen kann, funktionierts nur so mit printf(). Wie Anfangs aber erwähnt, geht das nur einschließlich bis zu den 64-Bit-Typen. std:cout akzeptiert ebenfalls diese Datentypen, sogar ohne spezielle Syntax. Lediglich bei den oben beiden genannten 128-Bit-Typen treten Anfangs beschriebene Probleme auf. Grüße Schlitzauge Zitieren
Klotzkopp Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 (bearbeitet) Es ist war lange her' date=' dass ich mit C++ gearbeitet habe, aber ich bin mir [u']sicher, dass die printf() so definitiv nicht aufgebaut wird.Wenn das Makro durch ein Stringliteral ersetzt wird, passt das. Hintereinanderstehende Stringliterale werden einfach verbunden. @DITTY: Diese Datentypen sind nicht Bestandteil des Standards, sondern ein Zusatzfeature deines Compilers. Insofern solltest du deine Compilerdokumentation bemühen. Falls dein Compiler zwar mit dem 128-Bit-Typ rechnen, aber ihn (noch) nicht ausgeben kann, kannst du dir natürlich auch eine Ausgabefunktion selbst schreiben. Bearbeitet 11. Oktober 2011 von Klotzkopp Zitieren
DITTY Geschrieben 11. Oktober 2011 Autor Geschrieben 11. Oktober 2011 Ich habe jetzt schon Stunden recherchiert und ja auch die Doku zu meinem Compiler durchforstet, ebenso zu den ganzen verwendeten Bilbtiotheken. Mir ist schon klar, dass die 128-Bit-Datentypen derzeit kein Standard sind. Habe ich aber auch nie gedacht und behauptet. Sie müssen auch kein Standard sein. Sie stehen aber auf meinem System zur Verfügung und dort möchte ich sie auch gerne einsetzen. Insofern ich keine Ausgaben damit machen möchte, funktioniert alles auch bestens. Mir geht es jetzt aber darum diese 128-Bit-Datentypen auszugeben. Und nein, ich plane nicht, extra hierfür einen eigenen 128-Bit-Datentyp zu schreiben. Natürlich bin ich selber auf die Idee gekommen und ich habe auch kein Problem damit sowas umzusetzen. Mir geht es aber EXPLIZIT um die beiden vom Compiler unterstützten Datentypen: __int128_t __uint128_t und deren Ausgabemöglichkeiten mit printf(,), std::cout oder auch meinetwegen mit anderen Methoden. Gerne würde ich auch eine eigene Methode zur Ausgabe dieser Datentypen schreiben, aber hab keinen blassen Schimmer wie. => Rückblende: Ich bin ja auf der Suche nach Möglichkeiten, diese Datentypen auszugeben. Wie, ist mir egal, solange sie auf meinem Screen landen. Da es bereits ähnliche Datentypen, z.B.: __int64_t gibt, und printf(,) unter obenstehender Syntaxanwendung damit klar kommt, ebenso std::cout, sogar ohne spezieller Syntaxanwendung, wäre mir natürlich eine Lösung mit printf() und/oder std::cout am liebsten. Wenn es etwas zur Ausgabe der 128-Bit-Typen in der Doku zu meinem Compiler oder in den Bibliotheken gibt, habe ich es nicht finden können. Deshalb suche ich ja Foren, wie dieses auf, mit der Hoffnung, dass mir Jemand Antworten / Lösungen auf das Problem geben kann. Könnte ja sein, dass jemand etwas in der Doku oder im Internet findet, welches ich übersehen habe. Oder vlt. hat schonmal jemand mit den genannten Datentypen gearbeitet. Gibt es für printf(,) oder cout spezielle Makros für die 128-Bit-Datentypen? Alles, was ich im Internet gefunden hab, zeigt nur Lösungen bis einschließlich den 64-Bit-Datentypen, aber auch ich finde gewiss nicht immer alles im WWW. Deshalb => Forum bzw. Foren. Grüße DITTY Zitieren
Klotzkopp Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 Gerne würde ich auch eine eigene Methode zur Ausgabe dieser Datentypen schreiben, aber hab keinen blassen Schimmer wie.Das ist doch eine Grundübung: Wiederholtes Dividieren durch 10 liefert dir als Divisionsrest die einzelnen Ziffern. Die musst du dann nur noch in umgekehrter Reihenfolge ausgeben. Das kannst du erreichen, indem du die Ziffern in einem Puffer sammelst, oder durch Rekursion. Zitieren
flashpixx Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 Auch wenn es OT ist, aber ich bei den meisten Problemen auch mathematischen Problemen reicht ein 64Bit Datentyp im Normalfall aus. Da der 128 Bittyp ja noch nicht im Standard ist, würde ich eigentlich darauf verzichten. Zitieren
DITTY Geschrieben 11. Oktober 2011 Autor Geschrieben 11. Oktober 2011 (bearbeitet) Irgendwie reden Wir Heute aneinander vorbei . Bin dennoch sehr dankbar für Eure Hilfen!!! (DAUMEN HOCH, gibts leider nicht als Smile => Anregung) Das ist doch eine Grundübung: Wiederholtes Dividieren durch 10 liefert dir als Divisionsrest die einzelnen Ziffern. Die musst du dann nur noch in umgekehrter Reihenfolge ausgeben. Das kannst du erreichen, indem du die Ziffern in einem Puffer sammelst, oder durch Rekursion. Stimmt. Na gut, klärt das Eine. Ich würde gerne aber lieber mit printf(,) oder std:cout arbeiten wollen. Ich kann mir beim besten Willen nicht vorstellen, dass die die Ausgabemöglichkeit vergessen haben, als se die 128-Bit-Integer implementiert haben. Mit __int64_t funktionierts doch auch, dank Makro und std:cout unterstützt´s direkt. Gibt es für printf() vlt. ein Makro für die genannten 128-Bit-Integer? Wie gesagt, "long double" selbst mit 2^512 unterstützt´s ja auch. Ja gut, Standard. Aber wenn jemand so einen Datentyp wie __int128_t implementiert, muss er es doch auch mal ausgegeben haben. Ich sehe in den Dokus nüscht. Kann da vlt. jemand mal schauen? Vlt. übersehe ich ja was Essentielles. Auch wenn es OT ist, aber ich bei den meisten Problemen auch mathematischen Problemen reicht ein 64Bit Datentyp im Normalfall aus. Da der 128 Bittyp ja noch nicht im Standard ist, würde ich eigentlich darauf verzichten. Ja, schon klar. Mir gehts rein vom Interesse aus. Wie ich das mit 64-Bit-Integer handhabe, weiß ich ja, wie ich bereits geschrieben habe. Mir gehts aber EXPLIZIT um diese beiden implementierten 128-Bit-Integer. THX und Grüße DITTY Bearbeitet 11. Oktober 2011 von DITTY Zitieren
Klotzkopp Geschrieben 11. Oktober 2011 Geschrieben 11. Oktober 2011 (bearbeitet) Ich würde gerne aber lieber mit printf(,) oder std:cout arbeiten wollen.Für cout kannst du dir selbst einen Ausgabeoperator schreiben. Ich kann mir beim besten Willen nicht vorstellen, dass die die Ausgabemöglichkeit vergessen haben, als se die 128-Bit-Integer implementiert haben.Anscheinend ist das eine recht neue Erweiterung des GCC, und ist auch nur für 64-Bit-Plattformen verfügbar. Ich vermute, die Entwickler sind einfach noch nicht soweit, oder behandeln das mit niedriger Priorität. Eine Spezialisierung von std::numeric_limits gibt's dafür offenbar auch noch nicht. Bei diesen Datentypen stand vermutlich die Berechnung im Vordergrund, nicht die Ein- und Ausgabe als Text. Ein Mensch kann mit Zahlen dieser Größenordnung ohnehin nicht viel anfangen. Aber wenn jemand so einen Datentyp wie __int128_t implementiert, muss er es doch auch mal ausgegeben haben.Da wäre mir bei Open Source aber schon Eigenartigeres begegnet Ich sehe in den Dokus nüscht. Kann da vlt. jemand mal schauen? Vlt. übersehe ich ja was Essentielles.Ich hab auf Anhieb auch nichts gefunden, nur ein paar Leute, die dasselbe Problem haben, aber auch da keine Antwort. Bearbeitet 11. Oktober 2011 von Klotzkopp Zitieren
DITTY Geschrieben 13. Oktober 2011 Autor Geschrieben 13. Oktober 2011 (bearbeitet) Habt großen Dank. Habs soweit jetzt hinbekommen. Hier ein Bsp.-Prog. für std::cout: INTS128.cpp: #include <climits> #include <cstdint> #include <cinttypes> #include <cfloat> #include <cmath> #include <cstdlib> #include <cstdio> #include <stdio.h> #include <iostream> using namespace std; std::ostream &operator<<(std::ostream &out, __uint128_t x) { if(x >= 10) { out << x / 10; } return out << static_cast<unsigned>(x % 10); } std::ostream &operator<<(std::ostream &out, __int128_t x) { if(x < 0) { out << '-'; x = -x; } return out << static_cast<__uint128_t>( x); } int main(int argc, char *argv[]) { __int128_t Var31 = 0, tmp31 = 0; __uint128_t Var32 = 0, tmp32 = 1; cout << "128-Bit Integer\n-----------------\n"; __int128_t INT128_MIN = (-170141183460469231731.687303715884105728) * pow(10,18); __int128_t INT128_MAX = ( 170141183460469231731.687303715884105727) * pow(10,18); //cout << "Vermutet:\nINT128-MIN:" << INT128_MIN << "\nINT128-MAX: " << INT128_MAX << "\n\nBerechnet:\n"; __int128_t TMP128 = 0; TMP128 = INT128_MAX + 1; // ergibt INT128-MIN cout << "INT128-MIN: " << TMP128 << "\n"; // Ausgabe von INT128-MIN TMP128 = INT128_MIN - 1; // ergibt INT128-MAX cout << "INT128-MAX: " << TMP128 << "\n"; // Ausgabe von INT128-MAX __uint128_t UINT128_MAX = (340282366920938463463.374607431768211455) * pow(10,18); __uint128_t UINT128_MIN = 0/* * pow(10,18)*/; __uint128_t TMPu128 = 0; TMPu128 = UINT128_MAX + 1; // ergibt UINT128-MIN cout << "UINT128-MIN: " << TMPu128 << "\n"; // Ausgabe von UINT128-MIN TMPu128 = UINT128_MIN - 1; // ergibt UINT128-MAX cout << "UINT128-MAX: " << TMPu128 << "\n"; // Ausgabe von UINT128-MAX getchar(); return 0; } OS: Linux x64-86 (bei mir Scientific Linux 6.1 x64 (up2date)) g++(GCC)-Version: g++ (GCC) 4.4.5 20110214 (Red Hat 4.4.5-6) Glibc: x86_x64 - v2.12-1.25.el6_1.3 Compile (release): g++ -std=c++0x -m64 -fopenmp -Wall -Wextra -pedantic -pedantic-errors -O3 -s source.cpp -o dest Output (exec): 128-Bit Integer ----------------- INT128-MIN: -170141183460469231731687303715884105728 INT128-MAX: 170141183460469231731687303715884105727 UINT128-MIN: 0 UINT128-MAX: 340282366920938463463374607431768211455 ----------------------- Wüsste noch jemand, wie man auch printf(,) dies beibringen kann? Und kann man und wenn ja wie, printf(,) weitere Makros beibringen? Ich wüsste da zwar jetzt ne Möglichkeit einfach einen Output mittels std:cout in eine String- bzw. char[]-Variable zu stecken und diese fprint(,) zu übergeben, allerdings würde ich nur ungern printf(,) mit std::cout kreuzen wollen. Lieber wäre mir, wenn ich wahlweise mein überladenes std::cout oder printf(,) verwenden könnte, ohne dass das eine vom anderen abhängig ist. THX im Voraus, Grüße DITTY Bearbeitet 13. Oktober 2011 von DITTY Zitieren
Klotzkopp Geschrieben 13. Oktober 2011 Geschrieben 13. Oktober 2011 Wüsste noch jemand, wie man auch printf(,) dies beibringen kann?Es ist leider nicht möglich, printf durch irgendwelche benutzerdefinierten Funktion beizubringen, wie es mit unbekannten Typen umgehen muss. Wenn die Implementierung deiner C-Standardbibliothek im Quellcode vorliegt, könntest du printf selbst ändern, aber damit müsstest du diese modifizierte Standardbibliothek mit deinem Programm verteilen. Und kann man und wenn ja wie, printf(,) weitere Makros beibringen?Printf kennt gar keine Makros. Dass in deinem Beispiel das Formatfeld für die 64-Bit-Typen durch ein Makro dargestellt wird, hat vermutlich nur den Grund, die Portierbarkeit zu erleichtern. Zitieren
DITTY Geschrieben 13. Oktober 2011 Autor Geschrieben 13. Oktober 2011 Also seht Ihr keinerlei Chance, dass printf(,) in der jetzigen Form, nicht mit den beiden Datentypen __int128_t und __uint128_t umgehen kann? Also was Ausgabe betrifft. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.