2014-09-02 6 views
17

Ich bin durch einen Unterschied im Verhalten zwischen MSVC und Klirren für diesen Code verwirrt:Wie sollte ein 64-Bit-Integer-Literal in C++ dargestellt werden?

#include <iostream> 
#include <cstdint> 

int main() { 
    int64_t wat = -2147483648; 
    std::cout << "0x" << std::hex << wat << std::endl; 

    return 0; 
} 

Visual Studio 2010, 2012 und 2013 (unter Windows 7) alle Display:

0x80000000 

Aber Klirren 503.0.40 (OSX) angezeigt:

0xffffffff80000000 

Was ist das richtige Verhalten nach dem C++ Standard? Soll das Literal auf 64 Bits null-erweitert oder vorzeichenerweitert werden?

Ich bin mir bewusst, dass int64_t wat = -2147483648LL; zu diesem gleichen Ergebnis auf beiden Compilern führen wird, aber ich frage mich über das richtige Verhalten ohne das literale Suffix.

+1

einen Blick C 11 ++ verändert in den empfindlicheren Verhalten geben Sie oben mit Klappern sind zu sehen - ich bin ein Sprach Anwalt sicher sein, weiter zu zitieren, Kapitel und Vers ... –

+0

@Paul R: Das "nicht-sensible" Verhalten existierte nur in C89/90, wo der Compiler "int", "long int" und den "unsigned long int" versuchen musste . Die Einbeziehung von unsigned Typ war eine schlechte Entscheidung, die in C099 und in der allerersten Version von C++ (C++ 98) aufgegeben wurde. Jetzt muss der Compiler nur signierte Typen in der Reihenfolge zunehmender Breite versuchen. In diesem Fall ist der einzige Unterschied von C++ 11 der Zusatz von 'long long int '. Es ist rein quantitativ. – AnT

+0

OK - danke - vielleicht habe ich mich zwischen C und C++ gemischt.FWIW Ich füge immer das explizite Suffix hinzu, also denke niemals darüber nach, wie das Verhalten sein soll. –

Antwort

13

Der Typ auf der linken Seite der Initialisierung spielt keine Rolle. Der Ausdruck -2147483648 wird von sich aus unabhängig interpretiert.

Literal 2147483648 hat keine Suffixe, was bedeutet, dass der Compiler zuerst versucht, es als int Wert zu interpretieren. Auf Ihrer Plattform ist int anscheinend ein 32-Bit-Typ. Der Wert 2147483648 liegt außerhalb des Bereichs des vorzeichenbehafteten 32-Bit-Integertyps. Der Compiler muss einen breiteren vorzeichenbehafteten ganzzahligen Typ verwenden, um den Wert darzustellen, wenn einer verfügbar ist (in der int, long int, long long int Sequenz, wobei der letzte formal ab C++ 11 verfügbar ist). Aber wenn kein ausreichend breit Signed Integer-Typ zur Verfügung steht, ist das Verhalten nicht definiert

In MSVC historisch long int hat die gleiche Breite wie int, wenn auch 64-Bit-long long int wird auch in späteren Versionen von MSVC unterstützt. Aber auch in VS2013 ich

warning C4146: unary minus operator applied to unsigned type, result still unsigned 

als Antwort auf Ihre Initialisierung (die long long int unterstützt). Dies bedeutet, dass MSVC sich immer noch an archaische C89/90-Regeln der ganzzahligen wörtlichen Interpretation hält (wobei Typen aus int, long int, unsigned long int Sequenz ausgewählt wurden).

Beachten Sie, dass MSVC offiziell kein C++ 11-Compiler ist. So muss es formal long long int nicht versuchen. Ein solcher Typ existiert in der Sprache pre-C++ 11 formal nicht. Von diesem Standpunkt aus hat MSVC keinen ausreichend großen vorzeichenbehafteten Integer-Typ, der in diesem Fall verwendet wird, und das Verhalten ist nicht definiert. Innerhalb der durch undefiniertes Verhalten gebotenen Freiheit ist die Verwendung von C89/90-Regeln für die ganzzahlige wörtliche Interpretation durchaus vertretbar.

Sie könnten auch an diesem ich das ein Gefühl haben (-2147483648> 0) returns true in C++?

+0

Ich denke, es hängt davon ab, ob Sie als C++ 11 kompilieren oder nicht? –

+0

@Paul R: Wie? Da C++ 98 "suffixless" Integer-Literale für "int" und "long int" versucht werden mussten. In MSVC haben beide normalerweise die gleiche Breite. – AnT

+0

Die Befehlszeile, die ich für MSVC verwende, ist 'cl wat.cpp/EHsc', also keine speziellen Flags außer der für die Ausnahmebehandlung. Ich glaube nicht, dass es in MSVC ein C++ 11-Flag gibt. –

Verwandte Themen