Die Multiplikation von zwei Ganzzahlen in C++
Ich habe eine ziemlich grundlegende Frage, aber ich bin nicht sicher, ob ich das Konzept zu verstehen oder nicht. Nehmen wir an, wir haben:
int a = 1000000;
int b = 1000000;
long long c = a * b;
Wenn ich diesen starte, c
zeigt den negativen Wert, also habe ich auch a
und b
zu long long
und dann war alles in Ordnung. Also warum muss ich ändern a
und b
, wenn Ihre Werte im Bereich von int
und Ihrem Produkt zugewiesen ist c
(das ist long long
)?
Ich bin mit C/C++
- Die int-Werte werden nicht gefördert, um die lange vor der Multiplikation, bleiben Sie ints und das Produkt als gut. Dann wird das Produkt gegossen, um die lange, aber zu spät, überlauf geschlagen hat. Mit einer von a oder b lange lange sollte so gut funktionieren, wie die anderen würde gefördert werden.
- Sollten Sie-tag die Programmiersprache, die Sie verwenden dazu führen, dass verschiedene Sprachen einführen, die sich anders Verhalten 😉
- Je nachdem, welche Maschine und die version von C, Sie sind mit der Größe eines 'int' kann sich ändern, wie gut.
- Sie sollten es machen, alle offiziellen und Zeug und copy/paste in eine Antwort haben, anstatt es slumming es als Kommentar. 🙂
- warum nicht ?:-)
- lange, lange c = ((long long)a*(long long)b);
- lange, lange c=(long)a*b
- Ich bevorzuge normalerweise nicht zum hinzufügen von tags im Titel, aber es ist fraglich
- Dies ist ein Duplikat einer meiner früheren Fragen stackoverflow.com/questions/29579112/...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
int
s werden nicht gefördert zulong long
vor der Multiplikation, bleiben Sieint
s, und das Produkt als gut. Dann wird das Produkt gegossen, umlong long
, aber zu spät, überlauf geschlagen hat.Dass sich ein
a
oderb
long long
sollte so gut funktionieren, wie die anderen würde gefördert werden.Für arithmetische Operatoren die Art des Ergebnis ist nicht davon abhängig, was Sie bei der Zuordnung das Ergebnis, aber die Typen der Operanden. Für arithmetische Operatoren die übliche arithmetische Umwandlungen durchgeführt werden, die auf den Operanden. Dieser wird eingesetzt, um die Operanden in einen gemeinsamen Typ, das heißt für Typen, die kleiner als unsigned/unterzeichnet int wenn die Werte passen, Sie sind gefördert zu unsigned/unterzeichnet int, in diesem Fall sind Sie bereits beide int, so dass keine Konvertierung erforderlich ist. Sehen Warum muss ein short konvertiert zu int, bevor arithmetische Operationen in C und C++? für die details, warum.
Was wir jetzt haben, ist Undefiniertes Verhalten, da Ganzzahl-überlauf ist ein nicht festgelegtes Verhalten, das ist in dem Entwurf der C++ - standard Abschnitt
5
[Expr], die sagt:Jetzt-a-Tage, die wir haben Desinfektionsmittel für den Fang dieser Arten zu undefiniertem Verhalten und mit
-fsanitize=undefined
mit beiden clang und gcc fangen diese zur Laufzeit mit folgender Fehlermeldung (sehen Sie es live):Referenz Abschnitt
5.6
[expr.mul] sagt:und Abschnitt
5
sagt:Es ist irgendwie absurd, weil der assembler-Anweisung ist immer berechnen
int * int -> 64 bit lange
also wenn man sich an den Maschinen-code, sehen Sie Folgendes :
imul
zu speichern, dass 64-bit in eax edx
dann
cdq
das setzen der bit-Zeichen von eax in edx (so verlieren die volle 64-bit Ergebnis)
und dann eax edx gespeichert sind, in das 64 bit-variable
und wenn Sie konvertieren Sie das 32-bit-Werte in 64-bit vor der Multiplikation, erhalten Sie einen Anruf, um die 64-bit-Multiplikation-Funktion für keinen Grund
(Ich geprüft : es ist nicht der Fall, wenn der code optimiert ist)