Frage Warum benutzen !! beim Konvertieren von Int in Bool?


Was kann ein Grund sein, auf diese Weise eine Ganzzahl in einen Booleschen Wert zu konvertieren?

bool booleanValue = !!integerValue;

statt nur

bool booleanValue = integerValue;

Alles, was ich weiß, ist, dass in VC ++ 7 Letzteres verursachen wird C4800 Warnung  und ersteres wird nicht. Gibt es einen anderen Unterschied zwischen den beiden?


75
2017-08-21 06:36


Ursprung


Antworten:


Die Probleme mit dem "!!" Idiom ist, dass es knapp ist, schwer zu sehen, leicht für einen Tippfehler zu verwechseln, einfach, eines der "!" s fallen zu lassen, und so weiter. Ich lege es in die Kategorie "Schau, wie süß wir mit C / C ++ sein können".

Einfach schreiben bool isNonZero = (integerValue != 0); ... klar sein.


110
2017-08-21 07:06



Historisch gesehen, die !! Idiom wurde verwendet, um sicherzustellen, dass Ihr Bool wirklich einen der beiden erwarteten Werte enthielt bool-ähnliche Variable, weil C und C ++ kein wahr hatten bool tippen und wir haben es gefälscht ints. Dies ist jetzt weniger ein Problem mit "echten" bools.

Aber benutzen !! ist ein effizientes Dokumentationsmittel (sowohl für den Compiler als auch für zukünftige Personen, die in Ihrem Code arbeiten), ja, Sie haben wirklich beabsichtigt, dies zu tun int zu einem bool.


49
2017-08-21 06:41



Weil! IntegerValue bedeutet integerValue == 0 und !! integerValue bedeutet also integerValue! = 0, ein gültiger Ausdruck, der ein bool zurückgibt. Letzteres ist eine Besetzung mit Informationsverlust.


13
2017-08-21 06:38



Es wird verwendet, weil die C-Sprache (und einige Vor-Standard-C ++ - Compiler zu) nicht die bool Tippe einfach int. Also die ints wurden verwendet, um logische Werte darzustellen: 0 sollte eigentlich bedeuten falseund alles andere war true. Das ! Betreiber kam zurück 1 von 0 und 0 von allem anderen. Doppelt ! wurde verwendet, um diese umzukehren, und es war da, um sicherzustellen, dass der Wert gerade ist 0 oder 1 abhängig von seinem logischen Wert.

In C ++, seit Einführung einer richtigen bool tippen Sie, das ist nicht mehr nötig. Sie können jedoch nicht alle Legacy-Quellen aktualisieren, und Sie sollten dies aufgrund der Abwärtskompatibilität von C mit C ++ (die meiste Zeit) nicht tun müssen. Aber viele Leute machen es immer noch, aus dem gleichen Grund: ihren Code rückwärtskompatibel zu alten Compilern zu halten, die immer noch nicht verstehen bools.

Und das ist die einzige wirkliche Antwort. Andere Antworten sind irreführend.


13
2017-08-28 09:58



Eine andere Option ist der ternäre Operator, der anscheinend eine Zeile weniger Assemblercode generiert (in Visual Studio 2005 sowieso):

bool ternary_test = ( int_val == 0 ) ? false : true;

was den Assembler-Code erzeugt:

cmp DWORD PTR _int_val$[ebp], 0
setne   al
mov BYTE PTR _ternary_test$[ebp], al

Gegen:

bool not_equal_test = ( int_val != 0 );

was produziert:

xor eax, eax
cmp DWORD PTR _int_val$[ebp], 0
setne   al
mov BYTE PTR _not_equal_test$[ebp], al

Ich weiß, es ist kein großer Unterschied, aber ich war neugierig und dachte nur, dass ich meine Erkenntnisse teilen würde.


6
2017-09-12 17:11



Ein Bool kann nur zwei Zustände haben, 0 und 1. Eine Ganzzahl kann einen beliebigen Zustand von -2147483648 bis 2147483647 annehmen, wobei eine 32-Bit-Ganzzahl mit Vorzeichen angenommen wird. Das Unäre! Der Operator gibt 1 aus, wenn der Eingang 0 ist und gibt 0 aus, wenn der Eingang alles außer 0 ist. So! 0 = 1 und! 234 = 0. Der zweite! schaltet einfach den Ausgang um, so dass 0 zu 1 wird und 1 zu 0 wird.

Die erste Anweisung garantiert also, dass booleanValue entweder auf 0 oder 1 gesetzt wird und kein anderer Wert, die zweite Anweisung nicht.


5
2017-08-21 06:48



!!ist ein idiomatischer Weg, um zu konvertieren bool, und es funktioniert, um den Visual C ++ - Compiler lahm zu halten, der sich über die angebliche Ineffizienz einer solchen Konvertierung lustig macht.

Ich sehe an den anderen Antworten und Kommentaren, dass viele Leute die Nützlichkeit dieses Idioms in der Windows-Programmierung nicht kennen. Was bedeutet, dass sie keine ernsthafte Windows-Programmierung vorgenommen haben. Und nehmen Sie blind an, dass das, was sie angetroffen haben, repräsentativ ist (ist es nicht).

#include <iostream>
using namespace std;

int main( int argc, char* argv[] )
{
    bool const b = static_cast< bool >( argc );
    (void) argv;
    (void) b;
}
> [d: \ dev \ test]
> cl foo.cpp
foo.cpp
foo.cpp (6): Warnung C4800: 'int': Erzwingt, dass der Wert auf 'true' oder 'false' gesetzt wird (Leistungswarnung)

[d: \ dev \ test]
> _

Und mindestens eine Person denkt, dass, wenn ein absoluter Neuling seine Bedeutung nicht erkennt, dann ist es nicht gut. Nun, das ist dumm. Es gibt eine Menge, die absolute Anfänger nicht erkennen oder verstehen. Es ist nichts für Profis, seinen Code so zu schreiben, dass er von jedem Anfänger verstanden wird. Nicht einmal für Studenten. Auf dem Weg des Ausschlusses von Operatoren und Operatorkombinationen, die absolute Novizen nicht erkennen ... Nun, ich habe nicht die Worte, um diesen Ansatz eine angemessene Beschreibung zu geben, Entschuldigung.

Prost & hth.,


4
2017-11-19 07:56