2014-05-18 14 views
5

Ich habe gehört, dass oft "alles" außer 0 ist wahr. Aber jetzt passieren mir sehr seltsame Dinge ... oder ich denke nur, dass ich es richtig mache, während ich es nicht tue. Hier ist, was passiert:Warum ~ (wahr^wahr) ist nicht wahr? Boole'sche Operatoren (Negation) funktionieren für `unsigned char`s, aber nicht für Bools? (C++)

Wenn ich überprüfen möchten, ob ein entspricht b, ich NOT(a XOR b) verwenden können. Als ich es für unsigned char ‚s überprüft, alles war in Ordnung, zum Beispiel

unsigned char a = 5; 
unsigned char b = 3; 
unsigned char c = ~(a^b); 

gab mir c == 249:

eine ist: 00000101, die 5. ist

b ist: 00000011, das ist 3.

~ (a^b) ist: 11111001, das ist 249.

Jetzt versuchen wir dies mit bool 's.

cout << ~(true^true) << ~(true^false) << ~(false^true) << ~(false^false) << endl; 
cout << ~(~(true^true)) << ~(~(true^false)) << ~(~(false^true)) << ~(~(false^false)) << endl; 

if (~(true^true) == true) 
    cout << "true"; 
else 
    cout << "false"; 

Das gibt mir in der Konsole:

-1-2-2-1 
0110 
false 

, während ich die erste Zeile zu erwarten:

1001 

Nach einem Freund zu fragen, riet er mir ! statt ~ zu versuchen, und sehen, ob es richtig funktioniert. Und (ich denke) es funktioniert jetzt richtig. Aber ich verstehe nicht warum. Sollte boolesche Negation für Bools nicht funktionieren?

+4

Boolesche Negation * macht * Arbeit für booleans. Es ist * bitweise-NICHT * das nicht. –

+1

Ein Bool hat mehr als ein Bit. ~ dreht jedes Bit um. – chris

+1

Es * ist * wahr, es ist einfach nicht * gleich * wahr '. –

Antwort

4

Ich habe gehört, dass oft „alles“ außer 0 wahr ist

Es gilt für Bedingungen, wie zum Beispiel in den if-Anweisung (hier und im Folgenden mir die C++ Standard-bin unter Berufung)

der Wert einer Bedingung, die ein Ausdruck ist der Wert des Ausdrucks ist , kontextuell zum Aussagen außer Schaltern

in bool umgewandelt wie

Zum Beispiel, wenn Sie schreiben würden

if (~(true^true)) 
    cout << "true"; 
else 
    cout << "false"; 

anstelle des Codes

if (~(true^true) == true) 
    cout << "true"; 
else 
    cout << "false"; 

Schnipsel oder wenn der logische Negationsoperator ! verwendet wird

9 Der Operanden der logischen Negationsoperator! wird kontextuell in bool umgewandelt (Abschnitt 4); Der Wert ist wahr, wenn der konvertierte Operand falsch und falsch ist. Der Typ des Ergebnisses ist bool

Wie für Bediener == dann

6 Wenn beiden Operanden der Arithmetik oder Aufzählungstypen, die üblichen arithmetischen Umwandlungen sind auf beiden Operanden durchgeführt werden; jeder der Operatoren soll true ergeben, wenn die angegebene Beziehung wahr ist, und false, wenn es falsch ist.

, dass im Falle von

if (~(true^true) == true) 

die üblichen arithmetischen Umwandlungs

angewendet wird, ist das Boolsche Wert TRUE umgewandelt Wert 1 bis ganze Zahl ist und es ist auf die Expression des linken operanf nicht gleich, weil interne binäre Darstellung des linken Operanden unterscheidet sich von 1, wie die Datenausgabe des ersten Codefragment zeigte ..

+0

Tolle Antwort, jetzt verstehe ich viel klar was wirklich passiert, danke! Wo finde ich den Standard, den du zitierst? Ich werde ein wenig verwirrt, während ich es in Google suche. – Kusavil

+1

@Kusavil Sie finden den Arbeitsentwurf des Standards unter http://www.open-std.org/jtc1/sc22/wg21/ –

2

~ ist ein bisschen NICHT.

z.B. ~ 0 ist 255 für vorzeichenloses Zeichen und 255! = true.

2

Es gibt einen Unterschied zwischen logischer Negation und bitweiser Negation. Die bitweise Negation kippt die Bits in der Variablen und die logische Negation kippt den logischen Wert, d. h. wahr/falsch. Stellen Sie sich beispielsweise die Zahl 5 vor, die binär als 101 dargestellt wird. Wenn Sie nur die Bits (~ 5) spiegeln, erhalten Sie 11111010, was nicht falsch ist, weil nur alle Nullen in C++ falsch sind. Aber wenn Sie (! 5) berechnen, erhalten Sie nur Nullen, die innerhalb einer Bedingung funktionieren würden.

9

Sie missverstehen die arithmetischen Konvertierungen. Wenn Sie ~e für einen Ausdruck e des Integraltyps sagen, wird der Wert zuerst auf mindestens int und dasselbe für e1^e2 (und für alle arithmetischen Ausdrücke, für diese Angelegenheit) heraufgestuft. So true^true ersten hat seine Operanden zu int befördert, wodurch 1^1, die in der Tat 0 ist, und damit Sie am Ende mit ~0, die auf Ihrer Plattform ist -1.

Sie können vage Sinn Ihres Betriebs machen, indem das Ergebnis zurück zu bool Umwandlung:

std::cout << static_cast<bool>(~(true^true)) 

In Ihrem letzten Problem, da Sie einen Ausdruck mit dem == Operator haben, wo die zwei Operanden verschiedene Typen haben, die beide Operanden werden zum gemeinsamen Typ hochgestuft, der wiederum int ist, und -1 unterscheidet sich von 1. Auch hier können Sie beide Operanden in bool konvertieren, um die gewünschte Gleichheit zu erhalten.


Die Meta Lektion ist, dass die integrierten Operatoren in C++ wirkt nur auf ganze Zahlen wirklich auf int arbeiten und breiter, aber nicht auf einen der kürzeren Typen (bool, char, short) (und ähnliche Überlegungen gelten Durchgehen von ganzen Zahlen durch eine Ellipse). Auch wenn dies manchmal Verwirrung stiften mag, vereinfacht es die Sprachregeln ein wenig, nehme ich an. Dies ist alles Teil des C-Erbes von C++.

+0

@RaphaelMiedl: Fertig, danke für das darauf hin. –

+0

Danke, ich glaube, ich verstehe jetzt :) – Kusavil

+1

"Missdeutes"? Ist das ein Wort, oder ist mir ein Witz über den Kopf gekommen? – Quentin

3

nur Ihr erstes Beispiel Anbetracht

~(true^true) 

Erstens, die Operanden von ^ zu int gefördert werden, so dass dies zu

entspricht
~(1^1) 

Dann xor von 1 mit sich selbst ergibt ein Allnull-Bitmusters, das unabhängig von int Darstellung den Wert 0 bedeutet:

~0 

Dies invertiert jedes Bit in der All-Nullen für 0 BitPattern, in einem Bitmuster alle 1-Bits ergibt, zB für 32-Bit-int,

int(0xFFFFFFFF) 

Mit der jetzt fast universal Komplement-Form Darstellung von signierten Zahlen der beiden ist dies dann der Wert -1.

Ihr Ausgang ist daher

-1