Ich weiß, dass die C- und C ++ - Standards viele Aspekte der Sprachimplementierung definiert lassen, nur weil es bei einer Architektur mit anderen Merkmalen sehr schwierig oder unmöglich wäre, einen standardkonformen Compiler dafür zu schreiben.
Ich weiß, dass vor 40 Jahren jeder Computer seine eigene Spezifikation hatte. Ich kenne jedoch keine Architekturen, die heute verwendet werden, wo:
CHAR_BIT != 8
signed
ist nicht die Ergänzung von zwei (ich habe gehört, Java hatte Probleme mit diesem).- Gleitkomma ist nicht IEEE 754-kompatibel (Bearbeiten: Ich meinte "nicht in IEEE 754-Binärcodierung").
Der Grund, den ich frage, ist, dass ich den Leuten oft erkläre, dass es gut ist, dass C ++ keine anderen Aspekte auf niedriger Ebene wie Typen mit fester Größe vorschreibt † . Es ist gut, weil es Ihren Code im Gegensatz zu "anderen Sprachen" bei korrekter Verwendung portabel macht (Bearbeiten: weil er auf mehr Architekturen portiert werden kann, ohne dass Emulationen von Aspekten der Maschine auf niedriger Ebene erforderlich sind, wie z. B. die Zweierkomplementarithmetik auf der Architektur mit Vorzeichen + Größe). . Aber ich fühle mich schlecht, dass ich selbst nicht auf eine bestimmte Architektur verweisen kann.
Die Frage ist also: Welche Architekturen weisen die oben genannten Eigenschaften auf?
† uint*_t
s sind optional.
quelle
Antworten:
Schauen Sie sich diesen an
Unisys ClearPath Dorado Server
bietet Abwärtskompatibilität für Personen, die noch nicht ihre gesamte Univac-Software migriert haben.
Wichtige Punkte:
CHAR_BIT == 9
Ich weiß nicht, ob sie einen C ++ - Compiler anbieten, aber sie könnten .
Und jetzt ist ein Link zu einer aktuellen Ausgabe ihres C-Handbuchs aufgetaucht:
Unisys C Compiler Programmierreferenzhandbuch
Abschnitt 4.5 enthält eine Tabelle mit Datentypen mit 9, 18, 36 und 72 Bit.
quelle
char*
undvoid*
muss die gleiche Größe und groß genug sein, um jeden anderen Zeiger zu halten. Der Rest liegt bei der Umsetzung.sizeof(int*) == 2
, aber Fernzeiger hatten auch einen 16-Bit-Selektorsizeof(void*) == 4
.sizeof(int*) != sizeof(char*)
hier nicht: beide sind 36 Bit. Der Byteselektor in thechar*
befindet sich jedoch auf den höherwertigen Bits und wird in ignoriertint*
. (Ich habe jedoch andere Maschinen verwendet, bei denen `sizeof (char *)> sizeof (int *).)void*
) immer die gleiche Größe. (Natürlich konnten Sie einen Funktionszeiger nicht in konvertierenvoid*
, da dieservoid*
möglicherweise kleiner ist. Aber gemäß dem Standard können Sie dies auch heute nicht tun.)Keine Ihrer Annahmen gilt für Mainframes. Für den Anfang kenne ich keinen Mainframe, der IEEE 754 verwendet: IBM verwendet Gleitkomma auf Basis 16, und beide Unisys-Mainframes verwenden Basis 8. Die Unisys-Maschinen sind in vielerlei Hinsicht etwas Besonderes: Bo hat den 2200 erwähnt Architektur, aber die MPS-Architektur ist noch seltsamer: 48-Bit-Wörter. (Ob das Wort ein Zeiger ist oder nicht, hängt von einem Bit im Wort ab.) Und die numerischen Darstellungen sind so gestaltet, dass es keinen wirklichen Unterschied zwischen Gleitkomma- und Integralarithmetik gibt: Der Gleitkomma ist Basis 8; Es erfordert keine Normalisierung und setzt im Gegensatz zu jedem anderen Gleitkomma, das ich gesehen habe, die Dezimalstelle rechts von der Mantisse und nicht links von der Mantisse und verwendet die vorzeichenbehaftete Größe für den Exponenten (zusätzlich zur Mantisse). Mit den Ergebnissen, dass ein integraler Gleitkommawert genau dieselbe Bitdarstellung hat (oder haben kann) wie eine Ganzzahl mit vorzeichenbehafteter Größe. Und es gibt keine Gleitkomma-Arithmetikbefehle: Wenn die Exponenten der beiden Werte beide 0 sind, führt der Befehl eine Integralarithmetik aus, andernfalls eine Gleitkomma-Arithmetik. (Eine Fortsetzung der Tagging-Philosophie in der Architektur.) Was bedeutet, dass während
int
kann 48 Bits belegen, 8 davon müssen 0 sein, oder der Wert wird nicht als Ganzzahl behandelt.quelle
Eine vollständige IEEE 754-Konformität ist bei Gleitkommaimplementierungen selten. Eine diesbezügliche Schwächung der Spezifikation ermöglicht viele Optimierungen.
Beispielsweise unterscheidet sich die Subnorm-Unterstützung zwischen x87 und SSE.
Optimierungen wie das Zusammenführen einer Multiplikation und Addition, die im Quellcode getrennt waren, ändern ebenfalls geringfügig die Ergebnisse, sind jedoch bei einigen Architekturen eine gute Optimierung.
Unter x86 erfordert die strikte IEEE-Konformität möglicherweise das Setzen bestimmter Flags oder zusätzliche Übertragungen zwischen Gleitkommaregistern und normalem Speicher, um die Verwendung des angegebenen Gleitkommatyps anstelle der internen 80-Bit-Gleitkommazahlen zu erzwingen.
Und einige Plattformen haben überhaupt keine Hardware-Floats und müssen sie daher in Software emulieren. Einige der Anforderungen von IEEE 754 sind möglicherweise teuer in der Implementierung in Software. Insbesondere die Rundungsregeln könnten ein Problem sein.
Mein Fazit ist, dass Sie keine exotischen Architekturen benötigen, um in Situationen zu geraten, in denen Sie nicht immer die strikte IEEE-Konformität garantieren möchten. Aus diesem Grund garantieren nur wenige Programmiersprachen eine strikte IEEE-Konformität.
quelle
long double
ein nützlicher und langlebiger Typ sein können, da das einzige wirkliche Problem darin bestand, dass es schlecht funktioniertprintf
. Die Tatsache, dass das erweiterte Doppel die führende 1 speichert, beschleunigt die Berechnungen auf Nicht-FPU-Systemen explizit und würde auch die Notwendigkeit einer speziellen Behandlung von Denormalen in einem anderen Kontext als der Konvertierung zu / von anderen Typen beseitigen. Schade, dass Cprintf
alles durcheinander gebracht hat.Ich habe diesen Link gefunden, in dem einige Systeme aufgelistet sind, bei denen
CHAR_BIT != 8
. Sie beinhaltenUnd natürlich gibt es eine Frage zum Stapelüberlauf: Welche Plattformen haben etwas anderes als 8-Bit-Zeichen?
Was Nicht-Zwei-Komplement-Systeme betrifft, gibt es eine interessante Lektüre auf comp.lang.c ++. Moderiert . Zusammenfassend: Es gibt Plattformen mit einer Komplement- oder Vorzeichen- und Größenrepräsentation.
quelle
CHAR_BIT=32
und Texas Instruments DSP von TMS32F28xx hatCHAR_BIT=16
. GCC 3.2 für PDP-10 hatCHAR_BIT=9
. Ich denke, S / 360 hat möglicherweise auch ein Nicht-8-Bit-Zeichen.CHAR_BITS
ein Teilduplikat ist.Ich bin mir ziemlich sicher, dass VAX-Systeme noch verwendet werden. Sie unterstützen kein IEEE-Gleitkomma. Sie verwenden ihre eigenen Formate. Alpha unterstützt sowohl VAX- als auch IEEE-Gleitkommaformate.
Cray-Vektor-Maschinen wie die T90 haben ebenfalls ein eigenes Gleitkomma-Format, obwohl neuere Cray-Systeme IEEE verwenden. (Der von mir verwendete T90 wurde vor einigen Jahren außer Betrieb genommen. Ich weiß nicht, ob noch einige aktiv sind.)
Der T90 hatte / hat auch einige interessante Darstellungen für Zeiger und ganze Zahlen. Eine native Adresse kann nur auf ein 64-Bit-Wort verweisen. Die C- und C ++ - Compiler hatten CHAR_BIT == 8 (erforderlich, da Unicos, eine Unix-Variante, ausgeführt wurde und mit anderen Systemen zusammenarbeiten musste), aber eine native Adresse konnte nur auf ein 64-Bit-Wort verweisen. Alle Byte-Ebene Operationen wurden durch den Compiler synthetisiert, und ein
void*
oderchar*
ein Byte in den höherwertigen 3 Bits des Wortes Offset gespeichert. Und ich denke, einige ganzzahlige Typen hatten Füllbits.IBM Mainframes sind ein weiteres Beispiel.
Andererseits müssen diese speziellen Systeme Änderungen des Sprachstandards nicht unbedingt ausschließen. Cray zeigte kein besonderes Interesse daran, seinen C-Compiler auf C99 zu aktualisieren. vermutlich dasselbe gilt für den C ++ - Compiler. Es könnte angemessen sein , die Anforderungen für gehostete Implementierungen, wie erforderlich CHAR_BIT == 8, IEEE - Format Gleitkommazahlen , wenn nicht die vollständige Semantik und 2's-Ergänzung ohne Füllbits für signierte ganze Zahlen zu straffen. Alte Systeme könnten weiterhin frühere Sprachstandards unterstützen (C90 starb nicht, als C99 herauskam), und die Anforderungen für freistehende Implementierungen (eingebettete Systeme) wie DSPs könnten geringer sein.
Andererseits könnte es gute Gründe für zukünftige Systeme geben, Dinge zu tun, die heute als exotisch gelten würden.
quelle
unsigned
integrale Typen ein großer Schmerz, während die signierte Arithmetik in Ordnung ist.CHAR_BITS
Laut gcc Quellcode:
CHAR_BIT
ist16
Bits für 1750a , dsp16xx- Architekturen.CHAR_BIT
ist24
Bits für die dsp56k- Architektur.CHAR_BIT
ist32
Bits für die c4x- Architektur.Sie können leicht mehr finden, indem Sie Folgendes tun:
oder
wenn
CHAR_TYPE_SIZE
entsprechend definiert ist.IEEE 754-Konformität
Wenn die Zielarchitektur keine Gleitkommaanweisungen unterstützt, generiert gcc möglicherweise einen Software-Fallback, der standardmäßig nicht dem Standard entspricht. Darüber hinaus können spezielle Optionen (z. B. die
-funsafe-math-optimizations
Deaktivierung der Vorzeichenerhaltung für Nullen) verwendet werden.quelle
Die binäre Darstellung nach IEEE 754 war auf GPUs bis vor kurzem ungewöhnlich, siehe GPU-Gleitkomma-Paranoia .
BEARBEITEN: In den Kommentaren wurde die Frage aufgeworfen, ob der GPU-Gleitkomma für die übliche Computerprogrammierung relevant ist, unabhängig von der Grafik. Auf jedenfall! Die meisten Hochleistungssachen, die heute industriell berechnet werden, werden auf GPUs ausgeführt. Die Liste umfasst KI, Data Mining, neuronale Netze, physikalische Simulationen, Wettervorhersage und vieles mehr. Einer der Links in den Kommentaren zeigt, warum: ein Gleitkomma-Vorteil von GPUs in der Größenordnung .
Eine andere Sache, die ich hinzufügen möchte, die für die OP-Frage relevanter ist: Was haben die Leute vor 10-15 Jahren getan, als GPU-Gleitkomma nicht IEEE war und als es keine API wie die heutige OpenCL oder CUDA gab, um GPUs zu programmieren? Ob Sie es glauben oder nicht, frühe Pioniere des GPU-Computing haben es geschafft, GPUs ohne API zu programmieren ! Ich habe einen von ihnen in meiner Firma getroffen. Folgendes hat er getan: Er codierte die Daten, die er zum Berechnen benötigte, als Bild mit Pixeln, die die Werte darstellen, an denen er arbeitete, und verwendete dann OpenGL, um die erforderlichen Operationen auszuführen (z. B. "Gaußsche Unschärfe", um eine Faltung mit normaler Verteilung darzustellen usw.) und dekodierte das resultierende Bild wieder in ein Array von Ergebnissen. Und das war immer noch schneller als mit CPU!
Solche Dinge veranlassten NVidia, ihre internen Datenbinärdateien endlich mit IEEE kompatibel zu machen und eine API einzuführen, die sich eher an Berechnungen als an Bildmanipulationen orientiert.
quelle
int f(int n) { return n <= 1 ? 1 : n * f(n-1); }
in CUDA ausführen ? Wenn nein, sind GPUs für diese Frage nicht relevant (die nach C- und C ++ - Komitees fragt).