Byte + Byte = int… warum?

365

Betrachten Sie diesen C # -Code:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

Das Ergebnis einer für byte(oder short) Typen durchgeführten Mathematik wird implizit auf eine Ganzzahl zurückgesetzt. Die Lösung besteht darin, das Ergebnis explizit in ein Byte umzuwandeln:

byte z = (byte)(x + y); // this works

Was ich mich frage ist warum? Ist es architektonisch? Philosophisch?

Wir haben:

  • int+ int=int
  • long+ long=long
  • float+ float=float
  • double+ double=double

Also warum nicht:

  • byte+ byte=byte
  • short+ short= short?

Ein bisschen Hintergrund: Ich führe eine lange Liste von Berechnungen für "kleine Zahlen" (dh <8) durch und speichere die Zwischenergebnisse in einem großen Array. Die Verwendung eines Byte-Arrays (anstelle eines int-Arrays) ist schneller (aufgrund von Cache-Treffern). Aber die umfangreichen Byte-Casts, die über den Code verteilt sind, machen ihn umso unlesbarer.

Robert Cartaino
quelle
10
Es ist nicht Erics Kenntnis des Standards , die hier nützlich wäre - es ist seine Kenntnis der Gestaltung der Sprache; was nicht warum. Aber ja, Erics Antwort wäre ziemlich definitiv :)
Jon Skeet
143
Die verschiedenen Überlegungen unten sind eine vernünftige Annäherung an die Entwurfsüberlegungen. Allgemeiner: Ich sehe Bytes nicht als "Zahlen"; Ich stelle sie mir als Muster von Bits vor, die als Zahlen, Zeichen, Farben oder was auch immer interpretiert werden könnten . Wenn Sie sie berechnen und als Zahlen behandeln möchten, ist es sinnvoll, das Ergebnis in einen Datentyp zu verschieben, der häufiger als Zahl interpretiert wird.
Eric Lippert
28
@Eric: Das macht viel Sinn für Byte, aber wahrscheinlich nicht so viel Sinn für kurz / kurz.
Jon Skeet
23
@Eric: byte1 | byte2behandelt sie überhaupt nicht als Zahlen. Dies behandelt sie genau als Muster von Bits. Ich verstehe Ihren Standpunkt, aber es kommt einfach so vor, dass ich jedes Mal, wenn ich in C # eine Arithmetik für Bytes durchgeführt habe, diese tatsächlich als Bits und nicht als Zahlen behandelte, und dieses Verhalten ist immer im Weg.
Roman Starkov

Antworten:

228

Die dritte Zeile Ihres Code-Snippets:

byte z = x + y;

bedeutet eigentlich

byte z = (int) x + (int) y;

Es gibt also keine + Operation für Bytes, Bytes werden zuerst in Ganzzahlen umgewandelt und das Ergebnis der Addition von zwei Ganzzahlen ist eine (32-Bit) Ganzzahl.

Azheglov
quelle
Ich habe unten Code ausprobiert, aber er funktioniert immer noch nicht. Byte z = (Byte) x + (Byte) y;
Anonym
10
Das liegt daran, dass es keine + Operation für Bytes gibt (siehe oben). Versuchen Sie Byte z = (Byte) ((int) x + (int) y)
Azheglov
35
Dies muss die richtigste und prägnanteste Antwort sein. Es gibt keinen Operanden, der zwischen Bytes hinzugefügt werden muss. Anstatt zu erklären, warum das Hinzufügen von zwei Bytes funktioniert oder nicht ( es ist nie passiert ), zeigt dies deutlich, warum das Ergebnis ein int ist, da nur 2 Ints addiert wurden .
RichardTheKiwi
2
Mir wurde schwindelig, als ich alle anderen Antworten las (keine Beleidigung für Mr. Jon Skeet). Ich fand, dass dies die einfachste Antwort ist, die richtig beschreibt, was unter der Haube vor sich geht. Vielen Dank!
Rayryeng
Hier ist eine Antwort, die ich an anderer Stelle geschrieben habe und die ein Programm enthält, mit dem ermittelt werden kann, wann diese vom Compiler gesteuerte automatische Heraufstufungint erfolgt: stackoverflow.com/a/43578929/4561887
Gabriel Staples
172

In Bezug auf "warum es überhaupt passiert" liegt es daran, dass es keine durch C # definierten Operatoren für die Arithmetik mit Byte, Sbyte, Kurz oder Ushort gibt, wie andere gesagt haben. In dieser Antwort geht es darum, warum diese Operatoren nicht definiert sind.

Ich glaube, es ist im Grunde genommen der Leistung zuliebe. Prozessoren haben native Operationen, um sehr schnell mit 32 Bit zu rechnen. Das Zurücksetzen der Konvertierung vom Ergebnis in ein Byte könnte automatisch erfolgen, würde jedoch zu Leistungseinbußen führen, wenn Sie dieses Verhalten nicht wirklich möchten.

Ich denke, dies wird in einem der kommentierten C # -Standards erwähnt. Suchen ...

EDIT: Ärgerlicherweise habe ich jetzt die kommentierte ECMA C # 2-Spezifikation, die kommentierte MS C # 3-Spezifikation und die Annotations-CLI-Spezifikation durchgesehen, und keiner von ihnen erwähnt dies, soweit ich sehen kann. Ich bin sicher, ich habe den oben angegebenen Grund gesehen, aber ich bin überwältigt, wenn ich weiß, wo. Entschuldigung, Referenzfans :(

Jon Skeet
quelle
14
Es tut mir leid, das zu sagen, aber ich finde das nicht die beste Antwort.
VVS
42
Haben Sie jede Antwort, die Sie als nicht die beste empfinden, abgelehnt ? ;)
Jon Skeet
55
(Nur um zu verdeutlichen, ich versuche es nicht wirklich mit Ihnen. Es scheint, dass jeder seine eigenen Kriterien für das Downvoting hat, und das ist in Ordnung. Ich stimme eine Antwort nur dann ab, wenn ich glaube, dass sie aktiv schädlich und nicht nur nicht ideal ist. )
Jon Skeet
21
Ich benutze die Abstimmung als Instrument, um die "beste" Antwort nach oben zu bekommen. Eigentlich habe ich festgestellt, dass Sie in Ihrer Antwort überhaupt nicht viel gesagt haben, was der Hauptgrund für meine Ablehnung war. Ein weiterer Grund ist vielleicht mein subjektives Gefühl, dass Ihr Repräsentant Ihnen einen großen Bonus beim Abstimmen gibt und Sie auf "besseren" Antworten landen.
VVS
23
IMO ist der beste Weg, um die "beste" Antwort nach oben zu bekommen, dies zu verbessern. Um ehrlich zu sein, ich denke , die meisten informative Antwort hier ist Kommentar Erics in der Frage ... aber anders als das, für die Design - Perspektive (im Gegensatz zu dem „ was der Compiler tun“ Perspektive) Ich glaube nicht , es ist viel Antwort jenseits von "Leistung". Insbesondere kaufe ich das Argument "Es verhindert Überlauf" (17 Stimmen) wirklich nicht, da dies auf int + int = long hindeuten würde.
Jon Skeet
68

Ich dachte, ich hätte das schon einmal gesehen. Aus diesem Artikel, The Old New Thing :

Angenommen, wir lebten in einer Fantasiewelt, in der Operationen an 'Byte' zu 'Byte' führten.

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

In dieser Fantasiewelt wäre der Wert von i 16! Warum? Da die beiden Operanden für den Operator + beide Bytes sind, wird die Summe "b + c" als Byte berechnet, was aufgrund eines ganzzahligen Überlaufs zu 16 führt. (Und wie ich bereits erwähnt habe, ist der Integer-Überlauf der neue Sicherheitsangriffsvektor.)

EDIT : Raymond verteidigt im Wesentlichen den Ansatz, den C und C ++ ursprünglich gewählt haben. In den Kommentaren verteidigt er die Tatsache, dass C # aus Gründen der Sprachabwärtskompatibilität denselben Ansatz verfolgt.

Michael Petrotta
quelle
42
Wenn wir Ganzzahlen hinzufügen und sie überlaufen, wird sie nicht automatisch als anderer Datentyp umgewandelt. Warum also mit Byte?
Ryan
2
Mit Ints läuft es über. Versuchen Sie, int.MaxValue + 1 hinzuzufügen. Sie erhalten -2147483648 anstelle von 2147483648.
David Basarab
8
@ Longhorn213: Ja, das sagt Ryan: int math kann überlaufen, aber int math gibt keine longs zurück.
Michael Petrotta
28
Genau. Wenn dies eine Sicherheitsmaßnahme sein soll, ist es eine sehr schlecht implementierte;)
Jon Skeet
5
@ Ryan: "faul" ist eine ziemlich heftige Anklage gegen die C # -Sprachendesigner, für etwas so Grundlegendes wie primitive Mathematik. Wenn Sie ihnen etwas vorwerfen möchten, machen Sie es "übermäßige Abwärtskompatibilität mit C / C ++".
Michael Petrotta
58

C #

ECMA-334 besagt, dass die Addition nur für int + int, uint + uint, long + long und ulong + ulong als legal definiert ist (ECMA-334 14.7.4). Als solche sind dies die Kandidatenoperationen, die in Bezug auf 14.4.2 zu berücksichtigen sind. Da es implizite Casts von Byte zu int, uint, long und ulong gibt, sind alle Additionsfunktionsmitglieder anwendbare Funktionsmitglieder unter 14.4.2.1. Wir müssen die beste implizite Besetzung durch die Regeln in 14.4.2.3 finden:

Das Casting (C1) nach int (T1) ist besser als das Casting (C2) nach uint (T2) oder ulong (T2), weil:

  • Wenn T1 int und T2 uint oder ulong ist, ist C1 die bessere Umwandlung.

Das Umwandeln von (C1) nach int (T1) ist besser als das Umwandeln von (C2) nach long (T2), da implizit von int nach long umgewandelt wird:

  • Wenn eine implizite Konvertierung von T1 nach T2 vorliegt und keine implizite Konvertierung von T2 nach T1 vorliegt, ist C1 die bessere Konvertierung.

Daher wird die Funktion int + int verwendet, die ein int zurückgibt.

Das ist alles ein sehr langer Weg, um zu sagen, dass es sehr tief in der C # -Spezifikation vergraben ist.

CLI

Die CLI arbeitet nur mit 6 Typen (int32, native int, int64, F, O und &). (ECMA-335 Partition 3, Abschnitt 1.5)

Byte (int8) gehört nicht zu diesen Typen und wird vor dem Hinzufügen automatisch zu einem int32 gezwungen. (ECMA-335 Partition 3, Abschnitt 1.6)

Alun Harford
quelle
Dass die ECMA nur diese bestimmten Operationen spezifiziert, würde eine Sprache nicht daran hindern, andere Regeln zu implementieren. VB.NET lässt byte3 = byte1 And byte2ohne Umwandlung hilfreich zu, löst jedoch nicht hilfreich eine Laufzeitausnahme aus, wenn int1 = byte1 + byte2ein Wert über 255 ausgegeben wird. Ich weiß nicht, ob Sprachen byte3 = byte1+byte2eine Ausnahme zulassen und auslösen würden, wenn diese 255 überschreitet, aber keine Ausnahme, wenn int1 = byte1+byte2Ausbeuten ein Wert im Bereich von 256-510.
Supercat
26

Die Antworten, die auf eine Ineffizienz beim Hinzufügen von Bytes und beim Zurückschneiden des Ergebnisses auf ein Byte hinweisen, sind falsch. x86-Prozessoren verfügen über Anweisungen, die speziell für den Ganzzahlbetrieb mit 8-Bit-Mengen entwickelt wurden.

Tatsächlich ist bei x86 / 64-Prozessoren die Ausführung von 32-Bit- oder 16-Bit-Operationen aufgrund des zu decodierenden Operandenpräfixbytes weniger effizient als 64-Bit- oder 8-Bit-Operationen. Auf 32-Bit-Computern ist das Ausführen von 16-Bit-Operationen mit derselben Strafe verbunden, es gibt jedoch immer noch dedizierte Opcodes für 8-Bit-Operationen.

Viele RISC-Architekturen verfügen über ähnliche native wort- / byteeffiziente Anweisungen. Diejenigen, die im Allgemeinen keinen Wert für das Speichern und Konvertieren in einen signierten Wert mit einer gewissen Bitlänge haben.

Mit anderen Worten, diese Entscheidung muss auf der Wahrnehmung des Byte-Typs beruhen, nicht auf zugrunde liegenden Ineffizienzen der Hardware.

Christopher
quelle
+1; Wenn nur diese Wahrnehmung nicht jedes Mal falsch wäre, wenn ich jemals zwei Bytes in C # verschoben und ODER-verknüpft hätte ...
Roman Starkov
Es sollten keine Leistungskosten für das Abschneiden des Ergebnisses anfallen. In der x86-Assembly ist es nur der Unterschied zwischen dem Kopieren eines Bytes aus dem Register oder vier Bytes aus dem Register.
Jonathan Allen
1
@ JonathanAllen Genau. Der einzige Unterschied besteht ironischerweise darin, eine erweiterte Konvertierung durchzuführen . Das aktuelle Design verursacht eine Leistungsstrafe für die Ausführung der Erweiterungsanweisung (entweder signierte Verlängerung oder nicht signierte Verlängerung)
Reirab
" Wahrnehmung dessen, wofür der Bytetyp ist " - Das mag dieses Verhalten für byte(und char) erklären , aber nicht, für shortdas semantisch eindeutig eine Zahl ist.
smls
13

Ich erinnere mich, dass ich einmal etwas von Jon Skeet gelesen habe (ich kann es jetzt nicht finden, ich werde weiter suchen), wie Byte den Operator + nicht wirklich überlastet. Wenn Sie zwei Bytes wie in Ihrem Beispiel hinzufügen, wird jedes Byte implizit in ein int konvertiert. Das Ergebnis davon ist offensichtlich ein int. Nun, WARUM dies so entworfen wurde, ich werde warten, bis Jon Skeet selbst etwas veröffentlicht :)

EDIT: Gefunden! Tolle Infos zu diesem Thema hier .

BKostenlos
quelle
9

Dies liegt am Überlauf und trägt.

Wenn Sie zwei 8-Bit-Zahlen hinzufügen, können diese in das 9. Bit überlaufen.

Beispiel:

  1111 1111
+ 0000 0001
-----------
1 0000 0000

Ich weiß es nicht genau, aber ich nehme an, dass ints, longsund doublesist mehr Raum gegeben , weil sie ziemlich groß sind , wie es ist. Außerdem handelt es sich um Vielfache von 4, die für Computer effizienter zu handhaben sind, da die Breite des internen Datenbusses 4 Byte oder 32 Bit (64 Bit werden jetzt immer häufiger) breit ist. Byte und Short sind etwas ineffizienter, können aber Platz sparen.

Samoz
quelle
23
Die größeren Datentypen folgen jedoch nicht dem gleichen Verhalten.
Inisheer
12
Probleme mit Überlauf sind ein Nebeneffekt. Wenn Sie Ihre Logik auf die Sprache anwenden würden, würden alle Datentypen nach der Additionsarithmetik einen größeren Datentyp zurückgeben, was definitiv NICHT der Fall ist. int + int = int, long + long = long. Ich denke, die Frage betrifft die Inkonsistenz.
Joseph
Das war mein erster Gedanke, aber warum ist int + int = long nicht? Ich kaufe also nicht das Argument "möglicher Überlauf" ... noch <grinsen>.
Robert Cartaino
11
Oh, und über das Argument "möglicher Überlauf", warum nicht Byte + Byte = kurz?
Robert Cartaino
A) Warum funktioniert es so, wie es funktioniert, wenn die Regeln von C # eingehalten werden? Siehe meine Antwort unten. B) Warum wurde es so entworfen, wie es ist? Wahrscheinlich nur Usability-Überlegungen, basierend auf subjektiven Beurteilungen darüber, wie die meisten Menschen Ints und Bytes verwenden.
mqp
5

Aus der C # -Sprachenspezifikation 1.6.7.5 7.2.6.2 Binäre numerische Heraufstufungen werden beide Operanden in int konvertiert, wenn sie nicht in mehrere andere Kategorien eingeteilt werden können. Ich vermute, sie haben den Operator + nicht überladen, um Byte als Parameter zu verwenden, sondern möchten, dass er sich normal verhält, sodass sie nur den Datentyp int verwenden.

C # Sprachspez

Ryan
quelle
4

Mein Verdacht ist, dass C # tatsächlich das operator+definierte on aufruft int(was ein zurückgibt, es intsei denn, Sie befinden sich in einem checkedBlock) und implizit beide bytes/ shortsto umwandelt ints. Deshalb erscheint das Verhalten inkonsistent.

mqp
quelle
3
Es schiebt beide Bytes auf den Stapel und ruft dann den Befehl "add" auf. Fügen Sie in IL "isst" die beiden Werte hinzu und ersetzen Sie sie durch ein int.
Jonathan Allen
3

Dies war wahrscheinlich eine praktische Entscheidung der Sprachdesigner. Immerhin ist ein int ein Int32, eine 32-Bit-Ganzzahl mit Vorzeichen. Wenn Sie eine Ganzzahloperation für einen Typ ausführen, der kleiner als int ist, wird sie ohnehin von den meisten 32-Bit-CPUs in ein 32-Bit-Int mit Vorzeichen konvertiert. Dies, zusammen mit der Wahrscheinlichkeit, dass kleine ganze Zahlen überlaufen, besiegelte wahrscheinlich den Deal. Dies erspart Ihnen die mühsame ständige Überprüfung auf Über- / Unterlauf. Wenn das Endergebnis eines Ausdrucks für Bytes im Bereich liegt, obwohl er in einem Zwischenstadium außerhalb des Bereichs liegt, erhalten Sie ein korrektes Ergebnis Ergebnis.

Ein weiterer Gedanke: Der Über- / Unterlauf dieser Typen müsste simuliert werden, da er auf den wahrscheinlichsten Ziel-CPUs nicht auf natürliche Weise auftreten würde. Warum die Mühe?

PeterAllenWebb
quelle
2

Dies ist größtenteils meine Antwort zu diesem Thema, die hier zunächst einer ähnlichen Frage gestellt wurde .

Alle Operationen mit ganzzahligen Integralzahlen kleiner als Int32 werden vor der Berechnung standardmäßig auf 32 Bit aufgerundet. Der Grund, warum das Ergebnis Int32 ist, besteht darin, es einfach so zu belassen, wie es nach der Berechnung ist. Wenn Sie die arithmetischen MSIL-Opcodes überprüfen, sind Int32 und Int64 die einzigen integralen numerischen Typen, mit denen sie arbeiten. Es ist "von Natur aus".

Wenn Sie das Ergebnis wieder im Int16-Format wünschen, ist es unerheblich, ob Sie die Umwandlung in Code durchführen oder der Compiler (hypotetisch) die Konvertierung "unter der Haube" ausgibt.

Zum Beispiel, um Int16-Arithmetik auszuführen:

short a = 2, b = 3;

short c = (short) (a + b);

Die zwei Zahlen würden auf 32 Bit erweitert, hinzugefügt und dann auf 16 Bit zurückgeschnitten, wie es MS beabsichtigt hatte.

Der Vorteil der Verwendung von Short (oder Byte) besteht hauptsächlich in der Speicherung in Fällen, in denen Sie über große Datenmengen verfügen (grafische Daten, Streaming usw.).

Kenan EK
quelle
1

Die Addition ist für Bytes nicht definiert. Also werden sie für die Hinzufügung zu int gegossen. Dies gilt für die meisten mathematischen Operationen und Bytes. (Beachten Sie, dass dies früher in älteren Sprachen der Fall war. Ich gehe davon aus, dass dies heute der Fall ist.)

Jim C.
quelle
0

Ich denke, es ist eine Entwurfsentscheidung darüber, welche Operation häufiger war ... Wenn Byte + Byte = Byte, werden möglicherweise viel mehr Menschen gestört, wenn sie in int umwandeln müssen, wenn ein int als Ergebnis erforderlich ist.

fortran
quelle
2
Ich bin ausnahmsweise einmal gestört :) Ich scheine immer das Bytergebnis zu brauchen, also muss ich immer werfen.
Roman Starkov
Außer du musst nicht auf int werfen. Die Besetzung ist implizit. Nur der andere Weg ist explizit.
Niki
1
@ Nikie Ich denke du hast meine Antwort nicht verstanden. Wenn das Hinzufügen von zwei Bytes ein Byte erzeugen würde, müsste jemand die Operanden (nicht das Ergebnis) vor dem Hinzufügen in int umwandeln , um Überläufe zu verhindern .
Fortan
0

Aus .NET Framework-Code:

// bytes
private static object AddByte(byte Left, byte Right)
{
    short num = (short) (Left + Right);
    if (num > 0xff)
    {
        return num;
    }
    return (byte) num;
}

// shorts (int16)
private static object AddInt16(short Left, short Right)
{
    int num = Left + Right;
    if ((num <= 0x7fff) && (num >= -32768))
    {
        return (short) num;
    }
    return num;
}

Vereinfachen Sie mit .NET 3.5 und höher:

public static class Extensions 
{
    public static byte Add(this byte a, byte b)
    {
        return (byte)(a + b);
    }
}

Jetzt können Sie tun:

byte a = 1, b = 2, c;
c = a.Add(b);

Serhio
quelle
0

Ich habe die Leistung zwischen Byte und Int getestet.
Mit int-Werten:

class Program
{
    private int a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (a + b);
        d = (a - b);
        e = (b / a);
        f = (c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

Mit Bytewerten:

class Program
{
    private byte a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (byte)(a + b);
        d = (byte)(a - b);
        e = (byte)(b / a);
        f = (byte)(c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

Hier das Ergebnis:
Byte: 3,57s 157mo, 3,71s 171mo, 3,74s 168mo mit CPU ~ = 30%
int: 4,05s 298mo, 3,92s 278mo, 4,28 294mo mit CPU ~ = 27%
Fazit:
Byte verbraucht mehr CPU, aber es kostet les Speicher und es ist schneller (möglicherweise, weil weniger Byte zuzuweisen ist)

Puipuix
quelle
-1

Zusätzlich zu all den anderen tollen Kommentaren dachte ich, ich würde einen kleinen Leckerbissen hinzufügen. Viele Kommentare haben sich gefragt, warum int, long und so ziemlich jeder andere numerische Typ dieser Regel nicht ebenfalls folgt. Geben Sie als Antwort auf arithmatisch einen "größeren" Typ zurück.

Viele Antworten haben mit der Leistung zu tun (32 Bit sind schneller als 8 Bit). In Wirklichkeit ist eine 8-Bit-Nummer immer noch eine 32-Bit-Nummer für eine 32-Bit-CPU. Selbst wenn Sie zwei Bytes hinzufügen, beträgt der Datenblock, mit dem die CPU arbeitet, unabhängig davon 32 Bit. Das Hinzufügen von Ints ist also nicht erforderlich sei "schneller" als das Hinzufügen von zwei Bytes ... es ist alles das Gleiche zur CPU. JETZT ist das Hinzufügen von zwei Ints schneller als das Hinzufügen von zwei Longs auf einem 32-Bit-Prozessor, da das Hinzufügen von zwei Longs mehr Mikroops erfordert, da Sie mit Zahlen arbeiten, die breiter als das Wort des Prozessors sind.

Ich denke, der grundlegende Grund dafür, dass Byte-Arithmetik zu Ints führt, ist ziemlich klar und direkt: 8 Bits gehen einfach nicht sehr weit! : D Mit 8 Bit haben Sie einen vorzeichenlosen Bereich von 0-255. Das ist nicht viel Platz zum Arbeiten ... die Wahrscheinlichkeit, dass Sie auf Byte-Einschränkungen stoßen, ist SEHR hoch, wenn Sie sie in der Arithmetik verwenden. Die Wahrscheinlichkeit, dass Ihnen bei der Arbeit mit Ints, Longs, Doubles usw. die Bits ausgehen, ist jedoch erheblich geringer ... so gering, dass wir sehr selten auf den Bedarf an mehr stoßen.

Die automatische Konvertierung von Byte nach Int ist logisch, da der Maßstab eines Bytes so klein ist. Die automatische Konvertierung von int nach long, float nach double usw. ist nicht logisch, da diese Zahlen eine signifikante Skalierung haben.

jrista
quelle
Dies erklärt immer noch nicht, warum byte - bytezurückkehrt intoder warum sie nicht zu short...
KthProg
Warum sollte die Addition einen anderen Typ als die Subtraktion zurückgeben? Wenn byte + bytezurückgegeben wird int, weil 255 + alles größer ist, als ein Byte enthalten kann, ist es unter dem Gesichtspunkt der Konsistenz des Rückgabetyps nicht sinnvoll, dass ein Byte minus ein anderes Byte etwas anderes als ein int zurückgibt.
Jrista
Ich würde nicht, es zeigt nur, dass der oben genannte Grund wahrscheinlich nicht richtig ist. Wenn es mit "Anpassen" an das Ergebnis zu tun bytehätte , würde die Subtraktion a byteund die Byte-Addition a zurückgeben short( byte+ bytepasst immer in a short). Wenn es um Konsistenz shortginge, wie Sie sagen, würde dies für beide Operationen eher ausreichen als int. Natürlich gibt es eine Mischung aus Gründen, von denen nicht alle unbedingt gut durchdacht sind. Oder der unten angegebene Leistungsgrund ist möglicherweise genauer.
KthProg