2009-09-22 26 views
75

ich diesen Code auf GNU C++ Compiler versuchen und nicht in der Lage ist, sein Verhalten zu verstehen:lange lange in C/C++

#include <stdio.h>; 

int main() 
{ 
    int num1 = 1000000000; 
    long num2 = 1000000000; 
    long long num3; 
    //num3 = 100000000000; 
    long long num4 = ~0; 

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3)); 
    printf("%d %ld %lld %llu", num1, num2, num3, num4); 
    return 0; 
} 

Als ich die Kommentarzeile Kommentar-, wird der Code nicht kompiliert und ein schenkt Fehler:

error: integer constant is too large for long type

Aber, wenn der Code kompiliert wird, wie es ist und ausgeführt wird, es erzeugt Werte viel größer als 10000000000.

Warum?

+6

Vielleicht zu spät, aber für zukünftige Leser schlage ich vor, dass Sie '' verwenden und 'uint64_t' verwenden. Um einen 64-Bit-Wert anzuzeigen, 'printf ("% "PRIu64" \ n ", val);' – enthusiasticgeek

Antwort

136

Die Buchstaben 100000000000 bilden eine Literal-Integer-Konstante, aber der Wert ist zu groß für den Typ int. Sie benötigen ein Suffix verwenden, um den Typ des Literals zu ändern, das heißt

long long num3 = 100000000000LL; 

Das Suffix LL die wörtliche macht in Art long long. C ist nicht "schlau" genug, um dies aus dem Typ auf der linken Seite zu schließen, der Typ ist eine Eigenschaft des Literals selbst, nicht der Kontext, in dem es verwendet wird.

+42

Zurück, als diese Antwort geschrieben wurde, war es wahrscheinlich richtig, aber jetzt sagt der C++ - Standard, dass der Typ eines Ganzzahl-Literals mit Nein Suffix ist das erste von "int", "long int" und "long long int", in denen sein Wert dargestellt werden kann. [C++ §2.14.2/2] Daher ist es jetzt nicht notwendig, das Suffix 'LL' in ein Integer-Literal einzufügen, das für andere Typen zu groß ist. – bames53

+8

Der Grund, warum dies ein Problem war, lag nicht daran, dass C++ nicht "intelligent" genug war, um den Literaltyp vom Typ der zugewiesenen Variablen zu ermitteln, sondern weil die Compiler-Erweiterung das erweiterte nicht implementiert hatte Integer-Typ, so dass es mit der Standardsprache gut funktionieren würde. C++ hat jetzt Regeln, so dass alle erweiterten Integer-Typen besser in den Standard integriert werden können: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf – bames53

+4

@unwind Ich denke, die Antwort sollte nach diesen Vorschlägen bearbeitet werden. – Antonio

25

Versuchen:

num3 = 100000000000LL; 

Und BTW, in C++ ist dies eine Compiler-Erweiterung, der Standard definiert nicht lange, lange, das ist Teil des C99.

+10

Nun, C++ 11 definiert jetzt lange lange –

1

Ihr Code kompiliert hier in Ordnung (auch mit dieser Linie unkommentiert. Musste es

num3 = 100000000000000000000; 

zu beginnen ändern, um die Warnung zu bekommen.

+0

Welcher Compiler? In C++ ist ein Integer-Literal das kleinere von int oder long, in das es passt. In C99 ist es das kleinste von int, long, long long. Wenn Sie also lange als C++ auf eine nicht standardmäßige Erweiterung zurückgreifen, hat Ihr Compiler möglicherweise auch die C99-Regeln für Literale übernommen. –

+0

GCC-Version 4.3.2 (Debian 4.3.2-1.1) auf einem 64-Bit-Linux-System. –

+0

Oh, so lange ist 64 Bit sowieso, oder? Macht Sinn. –

3

Es in hängt welchem ​​Modus Sie kompilieren. Lang lang ist nicht Teil des C++ - Standards, sondern nur (normalerweise) als Erweiterung unterstützt Dies betrifft den Typ der Literale Dezimal - Ganzzahl - Literale ohne Suffix sind immer vom Typ int Wenn int groß genug ist, um die Zahl zu repräsentieren, ansonsten Die Zahl ist sogar zu groß. Das Ergebnis ist implementationsdefiniert (p Robbable nur eine Anzahl von Typ long int, die aus Gründen der Abwärtskompatibilität abgeschnitten wurde). In diesem Fall müssen Sie explizit das LL-Suffix verwenden, um die lange lange Erweiterung zu aktivieren (bei den meisten Compilern).

Die nächste C++ - Version unterstützt offiziell long long in einer Weise, dass Sie kein Suffix benötigen, außer Sie möchten ausdrücklich, dass der Literaltyp mindestens lang ist. Wenn die Zahl nicht lange dargestellt werden kann, versucht der Compiler automatisch, long long auch ohne LL-Suffix zu verwenden. Ich glaube, das ist auch das Verhalten von C99.