2016-07-28 34 views
0

Vielleicht in alten Zeiten mussten sie sie trennen, um Speicher und verfügbaren Bereich für Datentypen effizient zu nutzen, aber jetzt müssen wir wirklich haben signed integer und unsigned integer?Programmiersprachen: Warum brauchen wir unsigned Datentypen?

+1

"alte Zeiten" - ich bin offiziell über den Hügel ;-) a) ziemlich oft Dinge sollten nicht -ve sein. b) 'unsigned' lässt mich ein größeres Maximum haben, wenn ich nicht will -ves. Ich würde c) und d) hinzufügen, aber Senilität tritt ein ... – John3136

+2

Vielleicht nicht für höhere Sprachen ... aber für Sprachen auf Systemebene geht es nicht nur um die effiziente Nutzung von Speicher. Es geht darum, dem Compiler genau zu sagen, was dieser Satz Bits bedeutet, damit Mathe richtig funktioniert. – cHao

Antwort

1

In C ist vorzeichenbehafteter Überlauf ein undefiniertes Verhalten, aber unsigned hat eine wohldefinierte base-2 Wraparound-Semantik. Dies ist ein sehr lästiges Relikt aus der Vergangenheit, da im Wesentlichen die gesamte Hardware Zweierkomplement verwendet. Sogar neue Sprachen wie Rust, die Zweierkomplemente annehmen, liefern zwar immer noch vorzeichenlose Typen.

Unsigned hat die wichtige Eigenschaft, dass es nicht negativ sein kann. Wenn Sie nicht nach negativen Array-Indizes suchen möchten, wenn Sie eine Eingabe einer Range-Prüfung unterziehen, können Sie unsigned verwenden.

Und für die Arbeit mit engen Typen, wie gepackte Pixelwerte oder Audio-Sample-Werte, ist es definitiv wichtig, ob sie signiert oder unsigniert sind. Es ist üblich, dass RGB- oder YUV-Pixel-Komponentenwerte [0..255] anstelle von [-128..127] vorzeichenlos sind. Dies bedeutet, dass die Skalierung (Multiplikation) mit einem Alpha-Wert ihren Abstand von Schwarz ändert und nicht ihre Entfernung vom mittleren Grau (signierte 0 liegt in der Mitte des Bereichs).

Sie könnten argumentieren, dass der vorzeichenlose 0..255-Bereich kann nur in einem breiteren Typ mit Vorzeichen verarbeitet werden, was wahr ist. Aber Sie müssen einen Weg finden, um zu definieren, dass die Konvertierung mit einer Nullerweiterung und nicht mit einer Zeichenerweiterung erfolgt. Noch wichtiger ist, dass die Verwendung von doppelt so viel Speicherbandbreite und Cache-Footprint für einen Grafikalgorithmus Bad Thing ist, da nicht alle Algorithmen einfach im laufenden Betrieb konvertieren können.

Auch extrem wichtig, mit kleineren Elementen bedeutet, dass mehr von ihnen auf einmal in eine SIMD vector passen. z.B. ein Vektor von 16 uint8_t gegen einen Vektor von 8 int16_t. So können Sie immer noch verlieren, indem Sie einfach Ihre Elemente im laufenden Betrieb erweitern.

+1

Für die MIPS-ISA kann der Zusatz "signed" eine Überlauf-Ausnahme generieren. Ohne einen separaten Ganzzahltyp mit Vorzeichen wäre es nicht möglich, auf diese Funktionalität in gewöhnlichem C zuzugreifen. Mit Wrap-Around-Unterlauf kann eine Bereichsüberprüfung von 0 bis N mit einem einzigen (x> N) -Test durchgeführt werden, da der Unterlauf einen sehr großen Wert erzeugt positiver Wert. Division durch Konstante ist auch ein wenig einfacher. –

+0

@ PaulA.Clayton: Die Range-Check-Optimierung ist etwas, was der Compiler sowieso tun kann und sollte, wenn Sie '10