webentwicklung-frage-antwort-db.com.de

Warum verursacht der negativste int-Wert einen Fehler bei mehrdeutigen Funktionsüberladungen?

Ich habe etwas über Funktionsüberladung in C++ gelernt und bin auf Folgendes gestoßen:

void display(int a)
{
    cout << "int" << endl;
}

void display(unsigned a)
{
    cout << "unsigned" << endl;
}

int main()
{
    int i = -2147483648;
    cout << i << endl; //will display -2147483648
    display(-2147483648);
}

Soweit ich verstanden habe, wird jeder Wert im Bereich int (in meinem Fall ist int 4 Byte) display(int) aufrufen, und jeder Wert außerhalb dieses Bereichs wird mehrdeutig sein ( da der Compiler nicht entscheiden kann, welche Funktion er aufruft). Sie gilt für den gesamten Wertebereich von int, mit Ausnahme des Mindestwerts, d. H. -2147483648, Bei dem die Kompilierung mit dem Fehler fehlschlägt

aufruf von überladenem display(long int) ist mehrdeutig

Wenn Sie jedoch den gleichen Wert auf ein int setzen und den Wert ausdrucken, erhalten Sie 2147483648. Ich bin buchstäblich mit diesem Verhalten verwechselt.

Warum wird dieses Verhalten nur beobachtet, wenn die negativste Zahl übergeben wird? (Das Verhalten ist dasselbe, wenn ein short mit -32768 Verwendet wird - in der Tat in jedem Fall, in dem die negative Zahl und die positive Zahl dieselbe Binärdarstellung haben.)

Verwendeter Compiler: g ++ (GCC) 4.8.5

88
infinite loop

Dies ist ein sehr subtiler Fehler. Was Sie sehen, ist eine Folge davon, dass es in C++ keine negativen Integer-Literale gibt. Wenn wir uns [Lex.icon] ansehen, erhalten wir ein Integer-Literal ,

Integer-Literal
Dezimal-Literal-Integer-Suffixopt
[...]

kann ein Dezimal-Literal sein,

Dezimal-Literal:
Ziffer ungleich Null
Dezimal-Literal opt Ziffer

wobei Ziffer [0-9] und Ziffer ungleich Null ist [1-9] Und das Suffix par können entweder u, U, l, L, ll oder LL. Nirgendwo hier ist - Als Teil des Dezimal-Literal enthalten.

In §2.13.2 haben wir auch:

Ein Integer-Literal ist eine Folge von Ziffern ohne Punkt oder Exponent, wobei einzelne Anführungszeichen bei der Bestimmung des Werts ignoriert werden können. Ein Integer-Literal kann ein Präfix haben, das seine Basis angibt, und ein Suffix, das seinen Typ angibt. Die lexikalisch erste Ziffer der Ziffernfolge ist die signifikanteste. Ein dezimales ganzzahliges Literal (Basis zehn) beginnt mit einer anderen Ziffer als 0 und besteht aus einer Folge von Dezimalstellen.

(Hervorhebung von mir)

Was bedeutet, dass der - In -2147483648 Der unäre operator - Ist. Das bedeutet, dass -2147483648 Tatsächlich als -1 * (2147483648) behandelt wird. Da 2147483648 Eins zu viel für Ihr int ist, wird es zu einem long int Befördert, und die Mehrdeutigkeit ergibt sich daraus, dass es nicht übereinstimmt.

Wenn Sie den minimalen oder maximalen Wert für einen Typ portabel abrufen möchten, können Sie Folgendes verwenden:

std::numeric_limits<type>::min();  // or max()
143
NathanOliver

Der Ausdruck -2147483648 Wendet tatsächlich den Operator - Auf die Konstante 2147483648 An. Auf Ihrer Plattform kann int2147483648 Nicht speichern. Es muss durch einen größeren Typ dargestellt werden. Daher ist der Ausdruck -2147483648 Nicht signed int, Sondern ein größerer vorzeichenbehafteter Typ, signed long int.

Da Sie für long keine Überladung angeben, muss der Compiler zwischen zwei Überladungen wählen, die beide gleichermaßen gültig sind. Ihr Compiler sollte einen Compilerfehler über mehrdeutige Überladungen ausgeben.

36

Erweitere die Antworten anderer


Um zu klären, warum das OP verwirrt ist, betrachten Sie zuerst das signed int binäre Darstellung von 2147483647 unten.

Largest signed int




Fügen Sie als Nächstes eine Nummer zu dieser hinzu : Geben Sie eine weitere signed int von -2147483648 (das das OP verwenden möchte) Smallest signed int



Endlich: Wir können sehen, warum das OP verwirrt ist, wenn -2147483648 kompiliert zu einem long int anstelle einer signed int, da es eindeutig in 32 Bit passt.

Aber, wie die aktuellen Antworten erwähnen, der unäre Operator (-) wird angewendet after2147483648 die ein long int und passt NICHT in 32 Bits.

4
bunkerdive