Frage

In Anbetracht der folgenden Ausschnitt:

#include <stdio.h>

typedef signed long long int64;
typedef signed int int32;
typedef signed char int8;

int main()
{
    printf("%i\n", sizeof(int8));
    printf("%i\n", sizeof(int32));
    printf("%i\n", sizeof(int64));

    int8 a = 100;
    int8 b = 100;
    int32 c = a * b;
    printf("%i\n", c);

    int32 d = 1000000000;
    int32 e = 1000000000;
    int64 f = d * e;
    printf("%I64d\n", f);
}

Die Ausgabe mit MinGW GCC 3.4.5 ist (-O0):

1
4
8
10000
-1486618624

Die erste Multiplikation wird ein int32 intern gegossenen (entsprechend den Assemblerausgang). Die zweite Multiplikation wird nicht gegossen. Ich bin nicht sicher, ob die Ergebnisse unterscheiden sich, da das Programm auf einem IA32 ausgeführt wurde, oder weil es irgendwo in der C-Standard definiert ist. Trotzdem interessiere ich, wenn genau dieses Verhalten irgendwo definiert ist (ISO / IEC 9899?), Weil ich wie um besser zu verstehen, warum und wenn ich manuell gegossen habe (ich habe Probleme, ein Programm von einer anderen Architektur zu portieren).

War es hilfreich?

Lösung

Der C99-Standard spezifiziert, dass binäre Operatoren wie * arbeitet nicht auf Integer-Typen kleiner als int. Ausdrücke dieser Art sind int gefördert, bevor der Bediener angewendet wird. Siehe 6.3.1.4 Absatz 2 und die zahlreichen Vorkommen der Worte „integer promotion“. Aber dies ist etwas orthogonal zu der Montageanleitung vom Compiler erzeugt wird, die auf ints arbeiten, da diese schneller ist, selbst wenn der Kompilierer erlaubt sein würde, um ein kürzeres Ergebnis berechnet (weil das Ergebnis sofort in einem L-Wert eines Kurztypen gespeichert ist zum Beispiel).

In Bezug auf int64 f = d * e; wo d und e vom Typ int ist, wird die Multiplikation als int in Übereinstimmung mit den gleichen Beförderungs Regeln. Der Überlauf ist technisch nicht definiertes Verhalten , Sie bekommen zwei-s-Komplement Ergebnis hier, aber man konnte alles nach dem Standard erhalten.

Hinweis: die Förderung Regeln distinguish und ohne Vorzeichen Typen bei der Förderung. Die Regel ist, kleinere Typen int zu fördern, es sei denn int nicht alle Werte des Typs darstellen kann, in welchem ??Fall unsigned int verwendet wird.

Andere Tipps

Das Problem ist, dass die Multiplikation ist int32 * int32, die als int32 durchgeführt wird, und das Ergebnis dann zu einem int64 zugeordnet. Sie würden den gleichen Effekt mit double d = 3 / 2; erhalten, die 3 durch 2 unter Verwendung von Integer-Division teilen würde, und assign 1,0 bis d.

Sie müssen achten Sie auf den Typ eines Ausdrucks oder subexpression, wann immer es eine Rolle kann. Dies erfordert Sicherstellen, dass der entsprechende Vorgang wird als geeignete Art berechnet, wie Gießen einen der Multiplikanden zu int64, oder (in meinem Beispiel) 3.0 / 2 oder (float)3 / 2.

Read K & R (das Original). Alle Integer-Operationen werden mit dem natürlichen Integer-Typ durchgeführt, es sei denn es handelt Variablen, die (oder gegossen), um etwas größer. Die Operationen auf char sind auf 32 Bits gegossen, weil das auf dieser Architektur die natürliche Größe der ganzen Zahl ist. Die Multiplikation der zwei 32-Bit-Integer ist in 32 Bit getan, weil nichts ist es etwas größer Gießen (bis Sie es auf die 64-Bit-Variablen zuweisen, aber das ist zu spät). Wenn Sie die Operation wollen in 64 Bits passieren, werfen einen oder beide ints auf 64 Bit.

int64 f = (int64)d * e;

a * b ist als int berechnet und dann an den Empfangsvariablentyp gegossen (die nur zufällig int sein)

d * e ist als int berechnet und dann an den Empfangsvariablentyp gegossen (die nur um int64 geschieht)

Wenn eine der Variablen vom Typ war größer, dass ein int (oder war Gleitkomma), als Typ verwendet worden wäre. Da aber alle die Typen in den Multiplikationen verwendet wurden, int oder kleiner wurden Ints verwendet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top