uint64_t und der sinnvolle Einsatz in C++
-
Hallo zusammen,
Ich Compiliere mein Projekt normalerweise mit aktuellen g++ Versionen. Ich verwende darin den Typ uint64_t. Dieser ist ja bekanntlich teil des C-Standards, aber nicht des C++ Standards. In C wird er also per typedef in der Regel zu einem long. Nun möchte allerdings jemand anders das Projekt für Mipsel compilieren und scheiterte am uint64_t Typ. Nach weiteren Nachforschungen ergab sich:
sizeof(int) = 4, sizeof(long) = 4.
uint64_t wurde daher vermutlich auf "long long" erweitert, welcher aber bekanntlich auch (noch) kein teil des C++ Standards ist.
Nun meine frage: Gibt es unter C++ eine definitiv sichere Möglichkeit eine 64bit-Ganzzahl zu bekommen? (32-bit ist definitiv zu wenig).
-> Frage 1: Gibt es im aktuellen Standard eine definitive Möglichkeit einen 64-bit unsigned int zu bekommen? 32 bit reichen definitiv nicht aus.Das Programm läuft theoretisch auch mit double statt uint64_t. entsprechende #ifdefs gibt es bereits. (die Genauigkeit ist nicht sooo wichtig, sondern wäre nur von Vorteil).
Allerdings müsste ich im Vorfeld überprüfen wie uint64_t aufgelöst wird und ob stdint.h existiert. Letzteres ist kein Problem. Wenn stdint.h nicht existiert -> auf double zurück greifen (ich verwende CMake um das raus zu finden). Die Frage ist nun aber, ob es eine schönere Möglichkeit gibt um raus zu finden ob uint64_t nun ein long long oder ein long ist (mit CMake). Derzeit überprüfe ich einfach sizeof(long). sollte diese 8 sein wird einfach gehofft dass uint64_t auch ein unsigned long long ist. Gibt es da was besseres um in jedem Fall richtige Ergebnisse zu erhalten?Vielen Dank!
Adrian
-
Kannst du boost verwenden?
http://www.boost.org/doc/libs/1_42_0/libs/integer/doc/html/boost_integer/cstdint.html
-
Danke schon mal für den link.
Boost würde ich nur ungern verwenden, da die Software auf diversen minimal-plattformen läuft (mipsel, ARM, symbian), für die sich boost nur schlecht verwenden lässt. Allerdings könnte ich mir den header von boost angucken und mich inspirieren lassen
Danke,
Adrian
-
Wenn du dich zu 100% an den Standard halten willst, kannst du eine Klasse schreiben, die dir 64-Bit Arithmetik bietet. Du musst dann halt sämtliche Operatoren implementieren. Das ganze wird dann intern mit zwei 32-Bit Zahlen umgesetzt. Das ist auch das, was der GCC normalerweise macht, wenn er mit 64-Bit Zahlen auf einen 32-Bit Prozessor rechnet.
Du kannst natürlich auch mal im Netz suchen. Es würde mich nicht wundern, wenn das nicht schon jemand implementiert hat.
Alternativ: Schau nach, ob der Compiler nicht doch schon einen 64-Bit Datentyp hat. Beim gcc heißt der, soweit ich weiß
long longbeim VC++ irgendwie anders. Das ist dann halt nicht standardkonform.
-
ProgChild schrieb:
soweit ich weiß
long longbeim VC++ irgendwie anders.Da heißt er auch long long, oder __int64.
-
ProgChild schrieb:
Wenn du dich zu 100% an den Standard halten willst, kannst du eine Klasse schreiben, die dir 64-Bit Arithmetik bietet. Du musst dann halt sämtliche Operatoren implementieren. Das ganze wird dann intern mit zwei 32-Bit Zahlen umgesetzt. Das ist auch das, was der GCC normalerweise macht, wenn er mit 64-Bit Zahlen auf einen 32-Bit Prozessor rechnet.
Du kannst natürlich auch mal im Netz suchen. Es würde mich nicht wundern, wenn das nicht schon jemand implementiert hat.
Alternativ: Schau nach, ob der Compiler nicht doch schon einen 64-Bit Datentyp hat. Beim gcc heißt der, soweit ich weiß
long longbeim VC++ irgendwie anders. Das ist dann halt nicht standardkonform.100% Standard Kompatibilität muss nicht sein, hauptsache es funktioniert.
Auf einen 64-bit datentyp prüfe ich ja derzeit mit einem sizeof(long) == 8. long long ist ja bekanntlich noch nicht standardisiert.. Mal sehen ob ich CMake dazu bewegen kann den zu erkennen.
Die eigene Klasse wäre natürlich eine Möglichkeit, auch wenn der Aufwand relativ hoch wäre (verhältnismäßig).
Da es also keinen definitiven 64-bit int im C++-Standard gibt, werd ich wohl doch den Compiler dynamisch abchecken müssen.Adrian
-
Normalerweise bringt jeder Compiler seine eigenen Typen mit. Mit uint64_t trifft man meist eine gute Wahl, da zumindest beim gcc stdint.h mitgeliefert wird. Dieser Header kann auch in einem C++ Projekt verwendet werden (nix mit boost).
uint64_t wurde daher vermutlich auf "long long" erweitert
Wie der Compiler das realisiert, ist ihm ueberlassen.
Nun möchte allerdings jemand anders das Projekt für Mipsel compilieren und scheiterte am uint64_t Typ.
Wie sieht der Fehler aus? Hat er (du) stdint.h inkludiert?
-
knivil schrieb:
Normalerweise bringt jeder Compiler seine eigenen Typen mit. Mit uint64_t trifft man meist eine gute Wahl, da zumindest beim gcc stdint.h mitgeliefert wird. Dieser Header kann auch in einem C++ Projekt verwendet werden (nix mit boost).
uint64_t wurde daher vermutlich auf "long long" erweitert
Wie der Compiler das realisiert, ist ihm ueberlassen.
Nun möchte allerdings jemand anders das Projekt für Mipsel compilieren und scheiterte am uint64_t Typ.
Wie sieht der Fehler aus? Hat er (du) stdint.h inkludiert?
Ja, hat er. Er bekommt jedoch Fehler dass der typ uint64_t unbekannt ist.
Und nein, es ist nicht dem Compiler überlassen wie er diese Typen implementiert.
Laut C99 Standard sind es, soviel ich weiß, immer typedefs auf die "normalen" typen in der aktuellen Implementierung. long kann nun entweder 32 oder 64 bit haben. long long wird normalerweise >= 64 bit haben (bin mir da aber nicht ganz sicher).
Wenn nun also long 32 bit hat wird der uint64_t typedef auf long long gesetzt. Der Datentyp long long existiert in C, weshalb stdint.h unter C gut funktioniert. Unter C++ existiert jedoch standardmäßig kein long long (und noch kein stdint.h/cstdint, erst ab c++0x), weshalb die Erweiterung uint64_t -> long long nicht funktioniert. Nur wenn uint64_t -> long gesetzt ist funktioniert das ganze.
Hab es nun so gelöst dass CMake beim Konfigurieren ein Testprogramm das uint64_t verwenden kompiliert, und im falle dass das fehlschlägt auf double zurück greift. Das funktioniert so hoffentlich besser.Adrian
-
Er bekommt jedoch Fehler dass der typ uint64_t unbekannt ist.
Und was hat ihn davon abgehalten, sich die stdint.h seines Compilers mal anzusehen? (Welchen Compiler nutzt er denn?) Bei mir steht z.B. ein Verweis auf tr1/cstdint drin. Kann also sein, dass es bereits im TR1 von C++ hinzugefuegt wurde.
Unter C++ existiert jedoch standardmäßig kein long long (und noch kein stdint.h
Ist doch egal, C++ hatte die Absicht, groesstenteils "abwaertskompatibel" zu sein. Mein g++ akzeptiert ohne zu murren uint64_t aus stdint.h.
-
knivil schrieb:
Ist doch egal, C++ hatte die Absicht, groesstenteils "abwaertskompatibel" zu sein.
Ja, aber zu C89. Die Sprache C entwickelt sich unterdessen unabhängig weiter (z.B.
restrict).Mit
<stdint.h>kann man sich jedenfalls nicht auf portables C++ verlassen, aber hier scheint dieses Kriterium sowieso nicht im Zentrum zu stehen.