9 Stimmen

Ist plain char normalerweise/immer vorzeichenlos auf nicht-twos-complement Systemen?

Offensichtlich sagt der Standard nichts darüber aus, aber ich bin mehr aus einem praktischen/historischen Standpunkt heraus interessiert: Haben Systeme mit nicht-zwei-komplementärer Arithmetik eine einfache char Typ, der vorzeichenlos ist? Andernfalls haben Sie möglicherweise alle Arten von Seltsamkeiten, wie zwei Darstellungen für den Nullterminator und die Unfähigkeit, alle "Byte"-Werte in char . Gibt/gab es solche merkwürdigen Systeme wirklich?

6voto

Michael Burr Punkte 320591

Das Null-Zeichen, das zur Beendigung von Zeichenketten verwendet wird, kann niemals zwei Darstellungen haben. Es ist wie folgt definiert (auch in C90):

Ein Byte, bei dem alle Bits auf 0 gesetzt sind, das so genannte Null-Zeichen, muss im Grundausführungszeichensatz vorhanden sein

Eine 'negative Null' auf einem Einser-Komplement würde also nicht ausreichen.

Abgesehen davon weiß ich wirklich nicht viel über C-Implementierungen, die nicht im Zweierkomplement sind. Ich habe vor langer Zeit an der Universität eine Einerkomplement-Maschine benutzt, kann mich aber nicht mehr an viel erinnern (und selbst wenn ich mich damals für den Standard interessiert hätte, war das, bevor er existierte).

5voto

DigitalRoss Punkte 138823

Es stimmt, in den ersten 10 oder 20 Jahren, in denen Computer kommerziell hergestellt wurden (in den 1950er und 60er Jahren), gab es anscheinend einige Unstimmigkeiten darüber, wie negative Zahlen im Binärformat dargestellt werden sollten. Tatsächlich gab es drei Anwärter:

  1. Das Komplement der Zwei, das nicht nur den Krieg gewann, sondern auch die anderen zum Aussterben brachte
  2. Die Ergänzung des einen, -x == ~x
  3. Vorzeichen-Magnitude, -x = x ^ 0x80000000

Ich denke, die letzte wichtige Einerkomplement-Maschine war wahrscheinlich die CDC-6600, damals die schnellste Maschine der Welt und der unmittelbare Vorgänger des ersten Supercomputers. 1.

Leider kann Ihre Frage nicht wirklich beantwortet werden, nicht weil niemand hier die Antwort kennt :-), sondern weil die Wahl nie getroffen werden musste. Und das war eigentlich für zwei Gründe:

  1. Das Zweierkomplement wurde gleichzeitig mit den Byte-Maschinen übernommen. Die Byte-Adressierung setzte sich mit dem IBM System/360 mit Zweierkomplement durch. Frühere Maschinen hatten keine Bytes, sondern nur vollständige Wörter hatte Adressen. Manchmal packten die Programmierer Zeichen in diese Wörter und manchmal verwendeten sie einfach das ganze Wort. (Die Wortlänge reichte von 12 bis 60 Bits.)

  2. C wurde erst ein Jahrzehnt nach den Bytemaschinen und dem Übergang zum Zweierkomplement erfunden. Punkt 1 geschah in den 1960er Jahren, C erschien erstmals in den 1970er Jahren auf kleinen Maschinen und eroberte die Welt erst in den 1980er Jahren.

Es gab also nie eine Zeit, in der eine Maschine über vorzeichenbehaftete Bytes, einen C-Compiler und ein anderes Datenformat als das Zweierkomplement verfügte. Die Idee von null-terminierten Strings war wahrscheinlich ein wiederholt erfundenes Designmuster, das sich ein Assembler-Programmierer nach dem anderen ausgedacht hat, aber ich weiß nicht, ob es bis zur C-Ära von einem Compiler spezifiziert wurde.

In jedem Fall ist das erste tatsächlich standardisierte C ("C89") gibt einfach an "ein Byte oder ein Code mit dem Wert Null wird angehängt" und aus dem Kontext geht klar hervor, dass sie versucht haben, unabhängig vom Zahlenformat zu sein. Daher ist "+0" eine theoretische Antwort, die aber in der Praxis vielleicht nie wirklich existiert hat.


1. Die 6600 war eine der wichtigsten Maschinen der Geschichte, und das nicht nur, weil sie schnell war. Sie wurde von Seymour Cray selbst entwickelt und führte die Out-of-Order-Ausführung und verschiedene andere Elemente ein, die später unter dem Begriff "RISC" zusammengefasst wurden. Obwohl andere versuchten, den Ruhm für sich zu beanspruchen, ist Seymour Cray der eigentliche Erfinder der RISC-Architektur. Es ist unbestritten, dass er den Supercomputer erfunden hat. Es ist tatsächlich schwer, einen früheren "Supercomputer" zu nennen, den er hat nicht Entwurf.

2voto

supercat Punkte 72939

Ich glaube, dass es für ein System fast, aber nicht ganz möglich wäre, einen Einser-Komplement-Typ "char" zu haben, aber es gibt vier Probleme, die nicht alle gelöst werden können:

  1. Jeder Datentyp muss als eine Folge von Zeichen dargestellt werden können, so dass, wenn alle Zeichenwerte, die zwei Objekte umfassen, identisch sind, die betreffenden Datenobjekte identisch sind.
  2. Jeder Datentyp muss ebenfalls als eine Folge von 'unsigned char' darstellbar sein.
  3. Die vorzeichenlosen Char-Werte, in die jeder Datentyp zerlegt werden kann, müssen eine Gruppe bilden, deren Ordnung eine Zweierpotenz ist.
  4. Ich glaube nicht, dass die Norm es zulässt, dass eine Einerkomplement-Maschine den Wert, der eine negative Null wäre, als Sonderfall behandelt und ihn als etwas anderes ausgibt.

Es könnte möglich sein, eine standardkonforme Maschine mit einem Einerkomplement oder einem vorzeichenbehafteten "char"-Typ zu haben, wenn die einzige Möglichkeit, eine negative Null zu erhalten, darin bestünde, einen anderen Datentyp zu überlagern, und wenn eine negative Null ungleich einer positiven Null ist. Ich bin mir nicht sicher, ob das standardkonform sein könnte oder nicht.

EDIT

BTW, wenn Anforderung 2 gelockert würde, frage ich mich, was die genauen Anforderungen wären, wenn andere Datentypen auf "char" überlagert werden? Während der Standard unter anderem klarstellt, dass man in der Lage sein muss, Zuweisungen und Vergleiche mit allen "char"-Werten durchzuführen, die sich aus der Überlagerung einer anderen Variablen mit einem "char" ergeben, weiß ich nicht, dass er vorschreibt, dass sich alle diese Werte wie eine arithmetische Gruppe verhalten müssen. Ich frage mich zum Beispiel, wie es um die Rechtmäßigkeit einer Maschine bestellt wäre, in der jede Speicherstelle physisch als 66 Bits gespeichert wird, wobei die obersten zwei Bits angeben, ob der Wert eine 64-Bit-Ganzzahl, ein 32-Bit-Speicher-Handle plus 32-Bit-Offset oder eine 64-Bit-Gleitkommazahl mit doppelter Genauigkeit ist. Da der Standard den Implementierungen erlaubt, alles zu tun, was sie wollen, wenn eine arithmetische Berechnung den Bereich eines vorzeichenbehafteten Typs überschreitet, würde das darauf hindeuten, dass sich vorzeichenbehaftete Typen nicht unbedingt als Gruppe verhalten müssen.

Für die meisten vorzeichenbehafteten Typen gibt es keine Anforderung, dass der Typ nicht in der Lage sein muss, Zahlen außerhalb des in limits.h angegebenen Bereichs darzustellen; wenn limits.h angibt, dass der Mindestwert für "int" -32767 ist, dann wäre es für eine Implementierung völlig legitim, tatsächlich einen Wert von -32768 zuzulassen, da jedes Programm, das dies versucht, ein nicht definiertes Verhalten hervorrufen würde. Die Schlüsselfrage wäre wahrscheinlich, ob es legitim wäre, dass ein "char"-Wert, der aus der Überlagerung eines anderen Typs resultiert, einen Wert außerhalb des in limits.h spezifizierten Bereichs ergibt. Ich frage mich, was der Standard sagt?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X