it-swarm.com.de

Warum ist (18446744073709551615 == -1) wahr?

Als ich an string::npos arbeitete, fiel mir etwas auf und ich konnte im Web keine Erklärung dafür finden. 

(string::npos == ULONG_MAX)

und 

(string::npos == -1)

sind wahr.

Also habe ich es versucht:

(18446744073709551615 == -1)

das ist auch wahr.

Wie kann das möglich sein? Ist es wegen binärer Konversation?

12
Bahadır

18,446,744,073,709,551,615

Diese Nummer 18,446,744,073,709,551,615 Ist tatsächlich 2^64 − 1. Wichtig hierbei ist, dass 2^64-1 Im Wesentlichen auf 0 basiert 2^64. Die erste Ziffer einer vorzeichenlosen Ganzzahl ist 0, Nicht 1. Wenn der Maximalwert also 1 Ist, hat er zwei mögliche Werte: 0 Oder 1 (2).

Schauen wir uns 2^64 - 1 In 64-Bit-Binärdateien an, alle Bits sind aktiviert.

1111111111111111111111111111111111111111111111111111111111111111b

Der -1

Schauen wir uns +1 Im 64-Bit-Binärformat an.

0000000000000000000000000000000000000000000000000000000000000001b

Um es im One's Compliment (OCP) negativ zu machen, invertieren wir die Bits.

1111111111111111111111111111111111111111111111111111111111111110b

Computer verwenden selten OCP, sie verwenden Two's Compliment (TCP). Um TCP zu erhalten, fügen Sie eine zu OCP hinzu.

1111111111111111111111111111111111111111111111111111111111111110b (-1 in OCP)
+                                                              1b (1)
-----------------------------------------------------------------
1111111111111111111111111111111111111111111111111111111111111111b (-1 in TCP)

"Aber, warte" fragst du, ob in Zweierkompliment -1 Steht,

1111111111111111111111111111111111111111111111111111111111111111b

Und wenn in binär 2^64 - 1 Ist

1111111111111111111111111111111111111111111111111111111111111111b

Dann sind sie gleich! Und genau das sehen Sie. Sie vergleichen eine 64-Bit-Ganzzahl mit Vorzeichen mit einer 64-Bit-Ganzzahl ohne Vorzeichen. In C++ bedeutet dies, dass der vorzeichenbehaftete Wert in vorzeichenlosen konvertiert wird, was der Compiler auch tut.

Aktualisieren

Für eine technische Korrektur danke an davmac in den Kommentaren ist die Konvertierung von -1, Die signed ist, in einen unsigned Typ der gleichen Größe tatsächlich in der Sprache angegeben, und keine Funktion der Architektur. Trotzdem ist die obige Antwort möglicherweise hilfreich, um die Arch/-Sprachen zu verstehen, die das Kompliment von zwei unterstützen, aber es fehlt die Spezifikation, um Ergebnisse zu erzielen, auf die Sie sich verlassen können.

10
Evan Carroll

string::npos ist definiert als constexpr static std::string::size_type string::npos = -1; (oder wenn es in der Klassendefinition definiert ist, wäre constexpr static size_type npos = -1; aber das ist wirklich irrelevant).

Der Umlauf von negativen Zahlen, die in unsignierte Typen konvertiert werden (std::string::size_type ist im Grunde std::size_t, der nicht vorzeichenbehaftet ist), ist im Standard perfekt definiert. -1 wird auf den größten darstellbaren Wert des vorzeichenlosen Typs umbrochen, der in Ihrem Fall 18446744073709551615 ist. Beachten Sie, dass der genaue Wert implementierungsdefiniert ist, da die Größe von std::size_t implementierungsdefiniert ist (aber in der Lage ist, die Größe des größtmöglichen Arrays auf dem betreffenden System zu speichern).

8
rubenvb

Gemäß dem C++ - Standard (Dokumentennummer: N3337 oder Dokumentennummer: N4296) wird std::string::npos folgendermaßen definiert

static const size_type npos = -1;

dabei ist std :: string :: size_type ein vorzeichenloser Integer-Typ. Es ist also nichts Wunderbares, dass std :: string :: npos gleich -1 ist. Der Initialisierer wird in die Type von std::string::npos konvertiert.

Wie für diese Gleichung

(string::npos == ULONG_MAX) is true,

dann bedeutet das, dass der Typ std::string::npos die verwendete Implementierung unsigned long eingibt. Dieser Typ entspricht normalerweise dem Typ size_t.

In dieser Gleichung

(18446744073709551615 == -1)

Das linke Literal hat einen vorzeichenlosen ganzzahligen Typ, der geeignet ist, ein so großes Literal zu speichern. Somit wird der rechte Operand auch in diesen vorzeichenlosen Typ konvertiert, indem das Vorzeichenbit propagiert wird. Da der linke Operand sich selbst als Maximalwert des Typs darstellt, sind sie gleich.

1

Hier geht es um einen signierten Überlauf und die Tatsache, dass negative Zahlen als 2s-Komplement gespeichert werden. Das bedeutet, dass Sie, um den absoluten Wert einer negativen Zahl zu erhalten, alle Bits invertieren und eins hinzufügen. Das bedeutet, wenn Sie einen 8-Bit-Vergleich durchführen, haben 255 und -1 den gleichen Binärwert von 11111111. Dasselbe gilt für größere Ganzzahlen

https://de.m.wikipedia.org/wiki/Two%27s_complement

0
doron