 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Andreas Volz Guest
|
Posted: Sun Mar 19, 2006 7:06 pm Post subject: Größe der Datentypen |
|
|
Hi,
ich hab ein Programm welches binäre Daten schreiben und einlesen können
soll. Das ganze soll auf Rechnern mit Little- und Big-Endian
Arbeitsweise funktionieren. Ich möchte eine Reihe von short und float
Werten abspeichern. Ich schreibe in die Daten mit Little-Endian und
muss die Bytereihenfolge auf dem Big-Endian Rechner tauschen.
Ich hab eine Funktion geschrieben die mir die Bytereihenfolge von short
und float vertauschen kann. Soweit ich das ganze gestetet habe
funktioniert es unter Linux (x86) und OS X (PowerPC). Dabei mache ich
aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
Ich habe keine Dokumente zu C++ gefunden, die das garantieren. Das ganze
ist OpenSource-Software. Ich kann also nicht ausschliessen, dass jemand
diesen Code auf einem mir unbekannten System mit einem mir unbekannten
Compiler übersetzt. Können dort andere Werte herauskommen? Wie verhalte
ich mich in diesem Fall? Soll das Programm zur Laufzeit mit sizeof die
Größe testen und dann einen Fehler melden? Kann man das schon beim
Kompilieren abfangen? Vielleicht mit dem Präprozessor oder GNU
autoconf. Oder wie gehe ich dieses Problem an (falls es den eines ist)?
Viele Fragen, hoffentlich kennst jemand Antworten dazu. :-)
Gruß
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Sven Hesse Guest
|
Posted: Sun Mar 19, 2006 7:31 pm Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
| Quote: | Dabei mache ich aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
|
Ja.
| Quote: | Ich habe keine Dokumente zu C++ gefunden, die das garantieren.
|
....Weil es keine gibt. Garantiert ist IIRC nur
sizeof(char) = 1
sizeof(short) <= sizeof(int) <= sizeof(long) (<= sizeof(long long))
sizeof(float) <= sizeof(double)
| Quote: | Kann man das schon beim
Kompilieren abfangen? Vielleicht mit dem Präprozessor oder GNU
autoconf.
|
Das ist eine mögliche (und relativ verbreitete) Methode...
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Jakob Bieling Guest
|
Posted: Mon Mar 20, 2006 12:06 am Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
| Quote: | sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
|
Jup.
| Quote: | Ich habe keine Dokumente zu C++ gefunden, die das garantieren.
|
Es gibt auch keine. Nur (teilweise) ueber die relative Groesse
zueinander, nur hilft dir das sicher auch nich.
| Quote: | Wie verhalte ich mich in diesem Fall?
|
Am besten waer, wenn deine Funktion mit verschiedenen Groessen
klarkommt. Dann waeren jedenfalls die Probleme fuer short und long schon
geloest.
Ein wahrscheinlich viel groesseres Problem wird sein, dass die
interne Darstellung von floating point Werten zwischen verschiedenen
Platformen mehr als nur in der Endianness abweichen kann. Der Standard
gibt keine Vorgaben, wie ein float gespeichert werden soll.
Was die interne Darstellung von integral types angeht, bin ich mir
nicht sicher.
| Quote: | Soll das Programm
zur Laufzeit mit sizeof die Größe testen und dann einen Fehler
melden? Kann man das schon beim Kompilieren abfangen?
|
Mit templates schon:
template <bool B> struct break_if { enum { is_true }; };
template <> struct break_if <true> { enum { is_false }; };
break_if <sizeof (short) != 2>::is_true;
Das waere z.B. eine moegliche Loesung. Ich glaube im boost Library
findet sich auch ein Compile-time assert, der ganz ganz aehnlich
funktioniert.
hth
--
jb
(reply address in rot13, unscramble first)
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Mon Mar 20, 2006 9:06 am Post subject: Re: Größe der Datentypen |
|
|
Sven Hesse wrote:
| Quote: | Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
Dabei mache ich aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
Ja.
Ich habe keine Dokumente zu C++ gefunden, die das garantieren.
...Weil es keine gibt. Garantiert ist IIRC nur
sizeof(char) = 1
sizeof(short) <= sizeof(int) <= sizeof(long) (<= sizeof(long long))
sizeof(float) <= sizeof(double)
|
Das ist nicht alles. Char muß mindestens 8 bit sein, short und int
mindestens 16 bit, long mindestens 32. Das steht so nicht direkt in der
Norm, aber es ergibt sich aus den Vorgaben für die Wertebereiche, die diese
Typen mindestens können müssen.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Andreas Volz Guest
|
Posted: Mon Mar 20, 2006 9:06 am Post subject: Re: Größe der Datentypen |
|
|
Am Sun, 19 Mar 2006 19:31:37 +0000 (UTC) schrieb Sven Hesse:
| Quote: | Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
Dabei mache ich aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
Ja.
|
Hm, das hab ich mir doch fast gedacht. Kennt jemand eine Plattform auf
welcher das oben nicht der Fall ist?
| Quote: | Ich habe keine Dokumente zu C++ gefunden, die das garantieren.
...Weil es keine gibt. Garantiert ist IIRC nur
sizeof(char) = 1
sizeof(short) <= sizeof(int) <= sizeof(long) (<= sizeof(long long))
sizeof(float) <= sizeof(double)
|
Ich habe hier (Linux/x86/gcc 3.3.6) ein kleinen Programm geschrieben
und die darunter stehende Ausgabe erhalten:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
printf ("sizeof (%s) = %d\n", "unsigned char", sizeof (unsigned
char)); printf ("sizeof (%s) = %d\n", "char", sizeof (char));
printf ("sizeof (%s) = %d\n", "unsigned short", sizeof (unsigned
short)); printf ("sizeof (%s) = %d\n", "signed short", sizeof (signed
short)); printf ("sizeof (%s) = %d\n", "unsigned int", sizeof (unsigned
int)); printf ("sizeof (%s) = %d\n", "int", sizeof (int));
printf ("sizeof (%s) = %d\n", "unsigned long", sizeof (unsigned
long)); printf ("sizeof (%s) = %d\n", "long", sizeof (long));
printf ("sizeof (%s) = %d\n", "float", sizeof (float));
printf ("sizeof (%s) = %d\n", "double", sizeof (double));
printf ("sizeof (%s) = %d\n", "long double", sizeof (long double));
printf ("sizeof (%s) = %d\n", "long long", sizeof (long long));
printf ("sizeof (%s) = %d\n", "unsigned long long", sizeof
(unsigned long lo ng));
printf ("sizeof (%s) = %d\n", "wchar_t", sizeof (wchar_t));
printf ("sizeof (%s) = %d\n", "bool", sizeof (bool));
return 0;
}
Ausgabe:
sizeof (unsigned char) = 1
sizeof (char) = 1
sizeof (unsigned short) = 2
sizeof (signed short) = 2
sizeof (unsigned int) = 4
sizeof (int) = 4
sizeof (unsigned long) = 4
sizeof (long) = 4
sizeof (float) = 4
sizeof (double) = 8
sizeof (long double) = 12
sizeof (long long) = 8
sizeof (unsigned long long) = 8
sizeof (wchar_t) = 4
sizeof (bool) = 1
Vielleicht kann mal jemand mit einer völlig ungewöhnlichen Plattform
das auf seinem Rechner ausführen und das Ergebnis hier posten oder mir
schicken. Mich würde einfach mal interessieren ob short/long/float
irgendwo auf einer realen Plattform abweicht. Falls nicht, dann teste
ich nur auf die Größe und breche im Fehlerfall ab. Falls ja, dann muss
ich mir eine alternative Implementierung überlegen.
Gruß
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Sven Hesse Guest
|
Posted: Mon Mar 20, 2006 10:49 am Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
| Quote: | Am Sun, 19 Mar 2006 19:31:37 +0000 (UTC) schrieb Sven Hesse:
Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
Dabei mache ich aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
Ja.
Hm, das hab ich mir doch fast gedacht. Kennt jemand eine Plattform auf
welcher das oben nicht der Fall ist?
|
Auf x86_64-Prozessoren ist es, soweit ich weiß, anders, hab jetzt aber
leider keinen entsprechenden Rechner vor mir...
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Andreas Volz Guest
|
Posted: Mon Mar 20, 2006 11:06 am Post subject: Re: Größe der Datentypen |
|
|
Am Sun, 19 Mar 2006 20:59:15 +0100 schrieb Jakob Bieling:
| Quote: | Ein wahrscheinlich viel groesseres Problem wird sein, dass die
interne Darstellung von floating point Werten zwischen verschiedenen
Platformen mehr als nur in der Endianness abweichen kann. Der
Standard gibt keine Vorgaben, wie ein float gespeichert werden soll.
|
Ja, da hab ich auch etwas im Internet gelesen. Ich meine aber auch
gelesen zu haben der IEEE legt da etwas fest. Es soll aber Plattformen
geben die das trotzdem anders machen. Auch hier würden mich reale
Beispiele interessieren, welche Plattformen es anders machen als die
"gängigen" x86-Plattformen. Es geht primär um eine 3D-Software. Ich
kann also damit leben, wenn ein Amiga von anno dazumal das anders macht.
Es geht um "reale" Rechner. :-)
Gruß
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Mon Mar 20, 2006 12:06 pm Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz wrote:
| Quote: | Am Sun, 19 Mar 2006 20:59:15 +0100 schrieb Jakob Bieling:
Ein wahrscheinlich viel groesseres Problem wird sein, dass die
interne Darstellung von floating point Werten zwischen verschiedenen
Platformen mehr als nur in der Endianness abweichen kann. Der
Standard gibt keine Vorgaben, wie ein float gespeichert werden soll.
Ja, da hab ich auch etwas im Internet gelesen. Ich meine aber auch
gelesen zu haben der IEEE legt da etwas fest. Es soll aber Plattformen
geben die das trotzdem anders machen. Auch hier würden mich reale
Beispiele interessieren, welche Plattformen es anders machen als die
"gängigen" x86-Plattformen.
|
Ein Beispiel wären die "gängigen" x86-Plattformen
Unter DOS im real mode hat int üblicherweise nur eine Breite von 16 bit.
Interessant wird's dann auch auf 64-bit-Plattformen, wo meines Wissens long
manchmal 64 bit breit is.
| Quote: | Es geht primär um eine 3D-Software. Ich kann also damit leben, wenn ein
Amiga von anno dazumal das anders macht. Es geht um "reale" Rechner.
|
Es soll auch DSPs geben, auf denen char, short und int 24 bit breit sind und
long 48 bits. Das sind durchaus "reale" Rechner, aber die werden dich
vermutlich auch nicht arg interessieren, weil sie selten für 3D-Grafik
genutzt werden.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Matthias Weißer Guest
|
Posted: Mon Mar 20, 2006 12:23 pm Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz schrieb:
| Quote: | Hi,
ich hab ein Programm welches binäre Daten schreiben und einlesen können
soll. Das ganze soll auf Rechnern mit Little- und Big-Endian
Arbeitsweise funktionieren. Ich möchte eine Reihe von short und float
Werten abspeichern. Ich schreibe in die Daten mit Little-Endian und
muss die Bytereihenfolge auf dem Big-Endian Rechner tauschen.
|
Wenn die Zeit zum Einlesen und die Dateigröße keine übergeordnete Rolle
spielen dann würde ich an deiner Stelle zu einem ASCII-Format greifen.
Damit umgehst du einen Großteil dieser Probleme. Der Dateigröße kannst
du mit einer Kompression (-> zlib) noch etwas nachhelfen.
--
Matthias Weißer
matthias (AT) matwei (DOT) de
http://www.matwei.de
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Heinz Ozwirk Guest
|
Posted: Mon Mar 20, 2006 3:43 pm Post subject: Re: Größe der Datentypen |
|
|
"Andreas Volz" <usenet-spam-trap (AT) brachttal (DOT) net> schrieb im Newsbeitrag news:20060319195813.63589030 (AT) frodo (DOT) mittelerde...
| Quote: | Hi,
ich hab ein Programm welches binäre Daten schreiben und einlesen können
soll. Das ganze soll auf Rechnern mit Little- und Big-Endian
Arbeitsweise funktionieren. Ich möchte eine Reihe von short und float
Werten abspeichern. Ich schreibe in die Daten mit Little-Endian und
muss die Bytereihenfolge auf dem Big-Endian Rechner tauschen.
Ich hab eine Funktion geschrieben die mir die Bytereihenfolge von short
und float vertauschen kann. Soweit ich das ganze gestetet habe
funktioniert es unter Linux (x86) und OS X (PowerPC). Dabei mache ich
aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
|
Selbst wenn du mit dieser Annahme keine Probleme bekommen würdest, gibt es noch genug andere Probleme. Was z.B. ist Little Endian und Big Endian? Für 2-Byte-Werte ist das ziemlich eindeutig definiert. Little Endian - niederwertiges Byte an niedriger Adresse, höherwertiges Byte an höherer Adresse. Aber wie ist das bei 4-Byte-Werten? Auf einigen Maschinen stehen die Bytes in der Reihenfolge b0, b1, b2, b3; bei einigen anderen in der Reihenfolge b3, b2, b1, b0. Aber was ist, wenn eine Maschine sie gerne als b1, b0, b3, b2 (oder war's b2, b3, b0, b1) sehen möchte. Auch solche Maschinen gibt es. Nicht ganz so häufig wie die anderen, aber es gibt sie.
Und was ist mit float und double? Da kann an nicht nur die einzelnen Bytes unterschiedlich anordnen, sondern die vorhandenen Bits auch anders aufteilen. Nicht jeder Rechner benutzt IEEE-schlag-mich-tod zur Darstellung von Fließkomma-Zahlen.
Und dann gibt es bei Strukturen auch noch das Problem des Padding und Alignment. Viel Spaß damit.
Binäre Daten sind ein denkbar schlechtes Format zum Austausch von Daten zwischen zwei Programmen. Das einzige, was da wirklich hilft, ist das Dateiformat genau und unabhängig von einer Programmiersprache zu beschreiben, jedes Byte einzeln, wie man aus mehreren Bytes Zahlen oder Strings macht usw. und dann eine Konvertierung zwischen den Byte-Folgen und sinnvollen Datenstrukturen (und umgekehrt zu implementieren). Aber jeder, der heute ein short (oder was auch immer) direkt in eine Datei schreibt, muss morgen damit rechnen, dass er es nicht mehr lesen kann. Das einzige, wovon man wirklich ausgehen kann, ist, dass in den nächsten Jahren wohl niemand mit einem bisschen Verstand ein Dateisystem entwickeln wird, das nicht auf Oktets basiert, und dass es in dieser Zeit wohl auch möglich sein wird, Oktets auf jedem Rechner zu lesen und zu schreiben.
HTH
Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Marcel Müller Guest
|
Posted: Mon Mar 20, 2006 3:54 pm Post subject: Re: Größe der Datentypen |
|
|
Hallo!
Andreas Volz schrieb:
| Quote: | ich hab ein Programm welches binäre Daten schreiben und einlesen können
soll. Das ganze soll auf Rechnern mit Little- und Big-Endian
Arbeitsweise funktionieren. Ich möchte eine Reihe von short und float
Werten abspeichern. Ich schreibe in die Daten mit Little-Endian und
muss die Bytereihenfolge auf dem Big-Endian Rechner tauschen.
|
Portable I/O-Implementierungen gibt es zu hauf. Auch für binäre Sachen.
Aber wenn es performant werden soll, implementiert man über Kurz oder
Lang auf die harte Tour, einmal für Little-Endian, einmal für
Big-Endian. Andere Kodierungen sind ja glücklicherweise zumindest nicht
üblich.
| Quote: | Ich habe keine Dokumente zu C++ gefunden, die das garantieren. Das ganze
ist OpenSource-Software. Ich kann also nicht ausschliessen, dass jemand
diesen Code auf einem mir unbekannten System mit einem mir unbekannten
Compiler übersetzt. Können dort andere Werte herauskommen? Wie verhalte
ich mich in diesem Fall? Soll das Programm zur Laufzeit mit sizeof die
Größe testen und dann einen Fehler melden? Kann man das schon beim
Kompilieren abfangen? Vielleicht mit dem Präprozessor oder GNU
autoconf. Oder wie gehe ich dieses Problem an (falls es den eines ist)?
|
Es gibt Header-Files, die Datentypen der Art int32_t, uint32_t etc.
definieren. Die haben garantierte Längen. stdint.h war es glaube ich.
Wie portabel das ist, sei mal dahingestellt. Zumindest Microsoft tanzt
mal wieder aus der Reihe. Aber vielleicht ist es auch ein gcc-Special
(auf verschiedenen Plattformen).
Das Problem ist so alt wie ungelöst. Aber die Architekturen sind auch
sehr unterschiedlich. Die T80x-CPUs können zum Beispiel hardwarebedingt
gar keine 16-Bit Werte (nur 8 und 32). Man kann das höchstens mit den
8-Bit Befehlen emulieren - im Slow-Motion-Modus.
Marcel
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Mon Mar 20, 2006 8:06 pm Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz wrote:
| Quote: | Am Sun, 19 Mar 2006 19:31:37 +0000 (UTC) schrieb Sven Hesse:
Andreas Volz <usenet-spam-trap (AT) brachttal (DOT) net> wrote:
Dabei mache ich aber folgende Annahmen:
sizeof (short) = 2
sizeof (long) = 4
sizeof (float) = 4
Die Frage ist nun, ob ich mit dieser Annahme Probleme bekommen kann?
Ja.
Hm, das hab ich mir doch fast gedacht. Kennt jemand eine Plattform auf
welcher das oben nicht der Fall ist?
|
War nicht die Alpha so ein Fall? (sizeof(long) == 8)
Und halt all die kommenden 64-bit-Plattformen.
| Quote: | #include <stdio.h
#include <stdbool.h
|
Das sind C(99)-Header. In C++ ist bool eingebaut, da braucht's kein
<stdbool.h>. Wenn du <stdbool.h> hast, hast du aber aller Wahrschein-
lichkeit nach auch <inttypes.h> und <stdint.h>, und darin findest du
Typen wie int32_t.
Ansonsten ist "eine Funktion schreiben, die bei einem short den Endian
tauscht" IMHO der falsche Ansatz. Besser ist "eine Funktion schreiben,
die eine ganze Zahl als little-endian in ein unsigned-char-Array
serialisiert" und das dazugehörige Gegenstück.
void storeU16(unsigned char out[], unsigned short value) {
out[0] = (value & 255);
out[1] = (value >> ;
}
unsigned short getU16(const unsigned char in[]) {
return in[0] + 256 * in[1];
}
Damit bleibt als einzige Annahme die Größe des unsigned char in Bits.
Wenn der unsigned short größer ist als 16 Bit (kleiner darf er lt. Norm
nicht sein), stört das hier nicht. Einfach nur Endian-tauschen-und-
rausschreiben klappt da nicht. Und dabei haben wir noch gar nicht mit
Strukturen und Padding angefangen :-)
Stefan
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
kanze Guest
|
Posted: Tue Mar 21, 2006 9:06 am Post subject: Re: Größe der Datentypen |
|
|
Andreas Volz wrote:
| Quote: | Am Sun, 19 Mar 2006 20:59:15 +0100 schrieb Jakob Bieling:
Ein wahrscheinlich viel groesseres Problem wird sein,
dass die interne Darstellung von floating point Werten
zwischen verschiedenen Platformen mehr als nur in der
Endianness abweichen kann. Der Standard gibt keine
Vorgaben, wie ein float gespeichert werden soll.
Ja, da hab ich auch etwas im Internet gelesen. Ich meine aber
auch gelesen zu haben der IEEE legt da etwas fest. Es soll
aber Plattformen geben die das trotzdem anders machen. Auch
hier würden mich reale Beispiele interessieren, welche
Plattformen es anders machen als die "gängigen"
x86-Plattformen. Es geht primär um eine 3D-Software. Ich kann
also damit leben, wenn ein Amiga von anno dazumal das anders
macht. Es geht um "reale" Rechner.
|
Auf "realen" Rechner, auch heute, gibt's wohl Unterschiede.
Sowie in der Größe eines Bytes (char) als in der Darstellung
negativer Zahlen. Es geht darum, wie portable du willst; wenn
man sich auf den gängigen Unix bzw. Windows Rechnern beschränkt,
sind die Unterschiede wesentlich geringer. Immerhin, als
Beispiele:
Intel 80x86 AMD 64 Sparc IBM
390 Unisys 2200
Bits in Byte 8 8 8
8 9
sizeof short 2 2 2
2 4?
sizeof long 4 8 4/8
4 4
neg. Ganzzahle 2er Kompl. 2er Kompl. 2er Kompl. 2er
Kompl. 1er Kompl.
Byte-Reihenf. 1234 1234 4321
4321 ??
Float IEEE IEEE IEEE
IBM ??
Die Länge eines longs auf einem Sparc hängt von einer Option des
Compilers.
Soweit ich weiß ist der Unisys 2200 der letzte der Dinosaurien.
früher gab es viele Rechner mit "komischen" Architekturen; heute
aber denke ich, dass der Unisys 2200 der letzte noch in
Produktion ist. (Auf den Unisys Serie A, z.B. war sizeof long 6,
und auf einem PDP-11 -- einem der gängigsten Rechner seiter
Zeit, war die Byte-Reihenfolge eines long 3412.)
In Allgemein, wenn man der meisten Portabilität zielt:
Für die Ganzzahlen:
Man arbeitet auf 16 und 32 Bits. Ggf. mit Überprüfung der
Werte bei der Ausgabe, um sicher zu sein, dass die Passen.
Bei der Ausgabe wird zuerst der Wert in den entsprechenden
unsigned Typ gewandelt. Die Norm C++ garantiert, dass der
Resultat dieser Umwandlung das Bitmuster des 2er Komplements
hat. Danach arbeitet man mit Verscheibung; ist der Protokol
Big-Endian, z.B.:
dest.put( (wert >> 24) & 0xFF ) ;
dest.put( (wert >> 16) & 0xFF ) ;
dest.put( (wert >> & 0xFF ) ;
dest.put( (wert ) & 0xFF ) ;
Beim Lesen macht man umgekehrt, zuerst wieder in einem
unsigned. Danach... In Theorie ist die Umwandlung unsigned
in signed Implementation-abhängig. Dazu hat man eventuell
mehr Bits as nötig -- auf dem Unisys, z.B. 0x0FFFFFFFF für
-1. Man könnte die Umwandlung selber programmieren, so
ungefahr (für 32 bits):
if ( (wert & 0x80000000ULL) == 0 ) {
ergebnis = wert ;
} else {
ergebnis = - (0x100000000ULL - wert) ;
}
Dieser Vorgang verlangt aber mindestens 33 Bits, also long
long auf vielen Rechnern und kostet zusetzliche Laufzeit.
Dazu ist er in der Praxis nur auf Außenseitern wie dem
Unisys nötig; auf allen gängigen Rechnern ist die Umwandlung
unsigned zu signed die Umkehrfunktion der Umwandlung
signed zu unsigned, wenn die Anzahl von Bits stimmt, und die
C-Typen int32_t, uint32_t, int16_t und uint16_t stehen zur
Verfügung, um Type zu haben, wo die Anzahl von Bits stimmt.
In meinem eigenen Code verwende ich die C-Type und die
eingebauten Umwandlungen, mit Verschiebung, um von der
Byte-Reihenfolge unabhängig zu sein.
Für die Gleitkomma:
Zum Schreiben benutze ich:
bool isNeg = source < 0 ;
if ( isNeg ) {
source = - source ;
}
int exp ;
if ( source == 0.0 ) {
exp = 0 ;
} else {
source = ldexp( frexp( source, &exp ), 24 ) ;
exp += 126 ;
}
unsigned long mant = source ;
dest.put( (isNeg ? 0x80 : 0x00) | exp >> 1 ) ;
dest.put( ((exp << 7) & 0x80) | ((mant >> 16) & 0x7F) ) ;
dest.put( mant >> 8 ) ;
dest.put( mant ) ;
Zum Lesen:
unsigned long tmp = source.get() << 24 ;
tmp |= source.get() << 16 ;
tmp |= source.get() << 8 ;
tmp |= source.get() ;
if ( *this ) {
float f = 0.0 ;
if ( (tmp & 0x7FFFFFFF) != 0 ) {
f = ldexp( ((tmp & 0x007FFFFF) | 0x00800000),
(int)((tmp & 0x7F800000) >> 23) - 126 - 24 )
;
}
if ( (tmp & 0x80000000) != 0 ) {
f = -f ;
}
dest = f ;
}
(Hier sind dest und source Instanze einer kleinen
Hilfsklasse, die schreibt bzw. liest einem iostream, und
kummert sich um eventuellen Fehler. Hier wird auch
Sonderwerte wie Inf und NaN nicht berücksichtigt.)
Damit soll auch das IBM-Format, und sogar alle möglichen
Formate, bedeckt sollen. Wenn man sich auf IEEE Format
beschränken akzeptiert, dann kann man halt uint32_t
schreiben und lesen (durch Verschiebung, wie oben), und
memcpy benutzen, zwischen float und uint32_t zu übertragen.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Michael Karcher Guest
|
Posted: Tue Mar 21, 2006 2:06 pm Post subject: Re: Größe der Datentypen |
|
|
kanze <kanze@gabi-soft.fr> wrote:
| Quote: | Beim Lesen macht man umgekehrt, zuerst wieder in einem
unsigned. Danach... In Theorie ist die Umwandlung unsigned
in signed Implementation-abhängig. Dazu hat man eventuell
mehr Bits as nötig -- auf dem Unisys, z.B. 0x0FFFFFFFF für
-1. Man könnte die Umwandlung selber programmieren, so
ungefahr (für 32 bits):
if ( (wert & 0x80000000ULL) == 0 ) {
ergebnis = wert ;
} else {
ergebnis = - (0x100000000ULL - wert) ;
}
Dieser Vorgang verlangt aber mindestens 33 Bits, also long
long auf vielen Rechnern und kostet zusetzliche Laufzeit.
|
Ich bin der Meinung, dass das ohne long long geht, und zwar so:
long long_from_dword(unsigned long data)
{
if(data < 0x80000000)
return data;
else
return (-static_cast<signed long>(0xFFFFFFFFUL-data))-1;
}
Natürlich kostet auch dieser Test Laufzeit, und ist daher unter Umständen
mit autoconf-artigen Zeug durch ein
inline long long_from_dword(unsigned long data)
{
return reinterpret_cast<signed long>(data);
}
zu ersetzen, wenn es auf Performance ankommt.
Michael Karcher
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Tue Mar 21, 2006 9:06 pm Post subject: Re: Größe der Datentypen |
|
|
Michael Karcher wrote:
| Quote: | kanze <kanze@gabi-soft.fr> wrote:
long long_from_dword(unsigned long data)
{
if(data < 0x80000000)
return data;
else
return (-static_cast<signed long>(0xFFFFFFFFUL-data))-1;
}
Natürlich kostet auch dieser Test Laufzeit
|
Obiges hab ich jetzt nicht ausprobiert, aber zumindest bei
inline int32 getInt32(const uint8* src)
{
uint32 u = getUint32(src, dif);
if(u & 0x80000000U)
return -1-~u;
else
return u;
}
was effektiv das gleiche bedeutet, optimiert der gcc das ganze Gerechne
vollständig weg. Da würde ich das von den höherpreisigen Compilern erst
recht erwarten :)
Stefan
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|