Wie in kurz C # erklärt (aber auch für andere Sprachcompiler wie Java)
Es gibt eine vordefinierte implizite Konvertierung von kurz nach int, long, float, double oder decimal.
Sie können nichtliterale numerische Typen mit größerer Speichergröße nicht implizit in kurze konvertieren (die Speichergrößen für integrale Typen finden Sie in der Tabelle der integralen Typen). Betrachten Sie zum Beispiel die folgenden zwei kurzen Variablen x und y:
short x = 5, y = 12;
Die folgende Zuweisungsanweisung führt zu einem Kompilierungsfehler, da der arithmetische Ausdruck auf der rechten Seite des Zuweisungsoperators standardmäßig int ergibt.
short z = x + y;
Verwenden Sie eine Besetzung, um dieses Problem zu beheben:
short z = (short)(x + y);
Es ist jedoch möglich, die folgenden Anweisungen zu verwenden, wenn die Zielvariable dieselbe Speichergröße oder eine größere Speichergröße hat:
int m = x + y;
long n = x + y;
Eine gute Anschlussfrage lautet:
"Warum wird der arithmetische Ausdruck auf der rechten Seite des Zuweisungsoperators standardmäßig mit int ausgewertet?"
Eine erste Antwort finden Sie in:
Klassifizieren und formales Überprüfen der ganzzahligen konstanten Faltung
Die Java-Sprachspezifikation definiert genau, wie Ganzzahlnummern dargestellt werden und wie Ganzzahlarithmetikausdrücke ausgewertet werden sollen . Dies ist eine wichtige Eigenschaft von Java, da diese Programmiersprache für die Verwendung in verteilten Anwendungen im Internet entwickelt wurde. Ein Java-Programm ist erforderlich, um unabhängig von der Zielmaschine, die es ausführt, dasselbe Ergebnis zu erzielen .
Im Gegensatz dazu ist C (und die Mehrheit der weit verbreiteten imperativen und objektorientierten Programmiersprachen) schlampiger und lässt viele wichtige Merkmale offen. Die Absicht hinter dieser ungenauen Sprachspezifikation ist klar. Dieselben C-Programme sollen auf einer 16-Bit-, 32-Bit- oder sogar 64-Bit-Architektur ausgeführt werden, indem die ganzzahlige Arithmetik der Quellprogramme mit den im Zielprozessor integrierten arithmetischen Operationen instanziiert wird. Dies führt zu einem viel effizienteren Code, da die verfügbaren Maschinenoperationen direkt verwendet werden können. Solange die Ganzzahlberechnungen nur Zahlen behandeln, die "ausreichend klein" sind, treten keine Inkonsistenzen auf.
In diesem Sinne ist die C-Integer-Arithmetik ein Platzhalter, der nicht genau durch die Programmiersprachenspezifikation definiert ist, sondern nur durch Bestimmen der Zielmaschine vollständig instanziiert wird.
Java definiert genau, wie Ganzzahlen dargestellt werden und wie Ganzzahlarithmetik berechnet werden soll.
Java Integers
--------------------------
Signed | Unsigned
--------------------------
long (64-bit) |
int (32-bit) |
short (16-bit) | char (16-bit)
byte (8-bit) |
Char ist der einzige vorzeichenlose Integer-Typ. Seine Werte repräsentieren Unicode-Zeichen von \u0000
bis \uffff
, dh von 0 bis 2 16 −1.
Wenn ein Ganzzahloperator einen Operanden vom Typ long hat, wird der andere Operand ebenfalls in den Typ long konvertiert. Andernfalls wird die Operation für Operanden vom Typ int ausgeführt. Falls erforderlich, werden kürzere Operanden in int konvertiert . Die Konvertierungsregeln sind genau festgelegt.
[Aus elektronischen Notizen in der Theoretischen Informatik 82 Nr. 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER , Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Karlsruhe, Deutschland]
T a, b; a += b
entsprichtT a, b; a = (T) (a + b)
: Bekanntmachung der Compiler-added gegossen.EDIT: Okay, jetzt wissen wir, dass es Java ist ...
In Abschnitt 4.2.2 der Java-Sprachspezifikation heißt es:
Mit anderen Worten, es ist wie bei C # - der Additionsoperator (wenn er auf integrale Typen angewendet wird) führt immer nur zu
int
oderlong
, weshalb Sie umwandeln müssen, um einershort
Variablen zuzuweisen .Ursprüngliche Antwort (C #)
In C # (Sie haben die Sprache nicht angegeben, also schätze ich) sind die einzigen Additionsoperatoren für primitive Typen:
int operator +(int x, int y); uint operator +(uint x, uint y); long operator +(long x, long y); ulong operator +(ulong x, ulong y); float operator +(float x, float y); double operator +(double x, double y);
Diese befinden sich in der C # 3.0-Spezifikation, Abschnitt 7.7.4. Zusätzlich wird die Dezimaladdition definiert:
(Dort werden auch das Hinzufügen von Aufzählungen, die Verkettung von Zeichenfolgen und die Kombination von Delegaten definiert.)
Wie Sie sehen, gibt es keinen
short operator +(short x, short y)
Operator. Daher werden beide Operanden implizit in int konvertiert und die int-Form wird verwendet. Das heißt, das Ergebnis ist ein Ausdruck vom Typ "int", daher muss gegossen werden.quelle
In C # und Java wird der arithmatische Ausdruck auf der rechten Seite der Zuweisung standardmäßig als int ausgewertet. Aus diesem Grund müssen Sie auf einen Short zurückgreifen, da es aus offensichtlichen Gründen keine implizite Konvertierungsform int to short gibt.
quelle
Da die Frage "Warum int standardmäßig" nicht beantwortet wurde ...
Erstens ist "Standard" nicht wirklich der richtige Begriff (obwohl nah genug). Wie von VonC festgestellt, hat ein Ausdruck, der aus Ints und Longs besteht, ein langes Ergebnis. Und eine Operation, die aus Ints / Logs und Doubles besteht, hat ein doppeltes Ergebnis. Der Compiler stellt die Begriffe eines Ausdrucks auf einen beliebigen Typ her, der einen größeren Bereich und / oder eine größere Genauigkeit im Ergebnis bietet (Gleitkommatypen haben vermutlich einen größeren Bereich und eine größere Genauigkeit als Integrale, obwohl Sie die Genauigkeit verlieren, wenn Sie große Longs in Double konvertieren).
Eine Einschränkung ist, dass diese Aktion nur zu den Bedingungen erfolgt, die sie benötigen. Im folgenden Beispiel verwendet der Unterausdruck 5/4 nur ganzzahlige Werte und wird mit ganzzahliger Mathematik ausgeführt, obwohl der Gesamtausdruck ein Doppel enthält. Das Ergebnis ist nicht das, was Sie erwarten könnten ...
(5/4) * 1000.0
OK, warum werden Byte und Short zu int heraufgestuft? Ohne Hinweise, die mich unterstützen, liegt es an der Praktikabilität: Es gibt eine begrenzte Anzahl von Bytecodes.
"Bytecode" verwendet, wie der Name schon sagt, ein einzelnes Byte, um eine Operation anzugeben. Zum Beispiel iadd , das zwei Ints hinzufügt. Derzeit sind 205 Opcodes definiert , und für jeden Typ werden 18 Ganzzahlen berechnet (dh insgesamt 36 zwischen Ganzzahl und Lang), wobei die Konvertierungsoperatoren nicht berücksichtigt werden.
Wenn kurz und Byte jeweils einen eigenen Satz von Opcodes haben, sind Sie bei 241, was die Erweiterungsfähigkeit der JVM einschränkt. Wie gesagt, keine Hinweise, die mich darauf stützen könnten, aber ich vermute, dass Gosling et al. "Wie oft benutzen die Leute tatsächlich Shorts?" Auf der anderen Seite führt das Heraufstufen von Byte zu int zu diesem nicht so wunderbaren Effekt (die erwartete Antwort ist 96, die tatsächliche ist -16):
byte x = (byte)0xC0; System.out.println(x >> 2);
quelle
>>
wirft zuint
?? Der Effekt ist jedoch das, was in Z80 alsSRA
(Verschiebung nach rechts arithmetisch) bezeichnet wird, wodurch Bits eines Bytes um 1 Stelle nach rechts verschoben werden, wobei das am weitesten rechts stehende verloren geht und das am weitesten links stehende (wobei ein vorzeichenbehaftetes Byte durch 2 geteilt wird) dupliziert wirdSRL
(logisch nach rechts verschieben), wodurch links ein Nullbit verbleibt (wie beim Teilen eines vorzeichenlosen Bytes durch 2), worauf die "erwartete Antwort" basiert.Welche Sprache benutzt du?
Viele C-basierte Sprachen haben die Regel, dass jeder mathematische Ausdruck in der Größe int oder größer ausgeführt wird. Aus diesem Grund ist das Ergebnis vom Typ int, sobald Sie zwei Kurzschlüsse hinzugefügt haben. Dies erfordert eine Besetzung.
quelle
Java verwendet für Berechnungen immer mindestens 32-Bit-Werte. Dies ist auf die 32-Bit-Architektur zurückzuführen, die 1995 bei der Einführung von Java üblich war. Die Registergröße in der CPU betrug 32 Bit und die arithmetische Logikeinheit akzeptierte 2 Zahlen der Länge eines CPU-Registers. Daher wurden die CPUs für solche Werte optimiert.
Dies ist der Grund, warum alle Datentypen, die arithmetische Optionen unterstützen und weniger als 32 Bit haben, in int (32 Bit) konvertiert werden, sobald Sie sie für Berechnungen verwenden.
Zusammenfassend war dies hauptsächlich auf Leistungsprobleme zurückzuführen und wird heutzutage aus Kompatibilitätsgründen beibehalten.
quelle
In Java mag jeder numerische Ausdruck:
anyPrimitive zas = 1; anyPrimitive bar = 3; ?? x = zas + bar
x ergibt immer mindestens ein int oder ein long, wenn eines der Additionselemente ein long war.
Aber es gibt einige harte Macken
byte a = 1; // 1 is an int, but it won't compile if you use a variable a += 2; // the shortcut works even when 2 is an int a++; // the post and pre increment operator work
quelle
AFAIS, niemand erwähnt die
final
Verwendung dafür. Wenn Sie Ihr letztes Beispiel ändern und die Variablen a und b alsfinal
Variablen definieren, kann der Compiler sicher sein, dass ihre Summe, Wert 5byte
, ohne Genauigkeitsverlust einer Variablen vom Typ zugewiesen werden kann . In diesem Fall kann der Compiler c die Summe von a und b zuweisen. Hier ist der geänderte Code:final byte a = 2; final byte b = 3; byte c = a + b;
quelle
final byte a = (byte) (new Random().nextInt(4));
undIncompatible types
erhebt sich wieder hässlicher Kopf. Es ist nicht nur Endgültigkeit, es ist in der Lage, es auf einen Wert zu kompilieren, der dem Typ entspricht.final
dass der Compiler versichert ist , und es kann nicht genug sein. Wenn wir Ihr Beispiel wörtlich nehmen, ist alles in Ordnung und gut. Aber versuchen Sie esb = 3
durchb = (byte)(new Random().nextInt(4))
. und inkompatible Typen sind zurück und a + b muss erneut gewirkt werden. Vielleicht möchten Sie das zu Ihrer Antwort hinzufügen.Jeder Datentyp, der niedriger als "int" ist (außer Boolean), wird implizit in "int" konvertiert.
In deinem Fall:
short a = 2; short b = 3; short c = a + b;
Das Ergebnis von (a + b) wird implizit in ein int konvertiert. Und jetzt weisen Sie es "kurz" zu. Damit Sie den Fehler erhalten.
short, byte, char - für all dies erhalten wir den gleichen Fehler.
quelle
Ich möchte etwas hinzufügen, auf das nicht hingewiesen wurde. Java berücksichtigt nicht die Werte, die Sie den Variablen (2 und 3) in ...
kurz a = 2; kurz b = 3; kurz c = a + b;
Soweit Java weiß, könnten Sie dies tun ...
kurz a = 32767; kurz b = 32767; kurz c = a + b;
Was außerhalb des Bereichs von short liegen würde, wird das Ergebnis automatisch in ein int gepumpt, da es "möglich" ist, dass das Ergebnis mehr als ein Short, aber nicht mehr als ein Int ist. Int wurde als "Standard" gewählt, da die meisten Leute im Grunde keine harten Codierungswerte über 2.147.483.647 oder unter -2.147.483.648 haben
quelle