Met behulp van logische operatoren op voor Booleans in C ++

stemmen
60

Is er een reden de logische operatoren op niet te gebruiken &, |, en ^ voor bool waarden in C ++?

Ik soms lopen in situaties waar ik wil precies één van de twee voorwaarden waar (XOR), dus ik gooi alleen de ^ operator in een voorwaardelijke expressie. Ik soms wil ook alle onderdelen van een aandoening die moet worden geëvalueerd of het resultaat waar is of niet (in plaats van kortsluiting), dus ik gebruik & en |. Ik moet ook Booleaanse waarden soms ophopen, en & = en | = kan erg nuttig zijn.

Ik heb gekregen een paar opgetrokken wenkbrauwen wanneer dit te doen, maar de code is nog steeds zinvol en schoner dan anders het geval zou zijn. Is er een reden om deze niet te gebruiken voor bools? Zijn er moderne compilers dat slechte resultaten geven?

De vraag is gesteld op 23/08/2008 om 18:52
user
In andere talen...                            


9 antwoorden

stemmen
7

De opgetrokken wenkbrauwen moet u zeggen genoeg om te stoppen met te doen. Je hoeft niet de code voor de compiler te schrijven, schrijf je het voor je mede-programmeurs en vervolgens voor de compiler. Zelfs als de samenstellers werken, verrassende andere mensen is niet wat je wilt - bitwise operators zijn voor bit operaties niet voor bools.
Ik veronderstel dat je ook eten appels met een vork? Het werkt, maar het verbaast mensen dus het is beter om het niet te doen.

antwoordde op 23/08/2008 om 19:00
bron van user

stemmen
45

||en &&zijn Booleaanse operatoren en de ingebouwde die zijn gegarandeerd om ofwel terug te keren trueof false. Niks anders.

|, &En ^zijn logische operatoren op. Wanneer het domein van de nummers die je werken op slechts 1 en 0, dan zijn ze precies hetzelfde, maar in de gevallen waarin uw booleans niet strikt 1 en 0 - zoals het geval is met de taal C - kan je eindigen met een aantal gedrag je niet wilt. Bijvoorbeeld:

BOOL two = 2;
BOOL one = 1;
BOOL and = two & one;   //and = 0
BOOL cand = two && one; //cand = 1

In C ++, maar de boolsoort is gegarandeerd alleen ofwel een te zijn trueof een false(die impliciet respectievelijk om te zetten 1en 0), dus het is minder van een zorg van dit standpunt, maar het feit dat mensen niet worden gebruikt om dergelijke dingen in de code te zien maakt een goed argument om het niet te doen. Zeg gewoon b = b && xen worden gedaan met het.

antwoordde op 23/08/2008 om 19:06
bron van user

stemmen
2

Patrick maakte goede punten, en ik ben niet van plan om ze te herhalen. Toch zou ik stel voor het verminderen van 'if' verklaringen leesbaar Engels waar mogelijk door het gebruik van goed-vernoemd boolean vars.For voorbeeld, en dit is het gebruik van Booleaanse operatoren, maar je kan evengoed gebruiken bitwise en op de juiste naam van de bools:

bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
 .. stuff ..
}

Je zou denken dat het gebruik van een boolean lijkt overbodig, maar het helpt met twee belangrijke dingen:

  • De code is makkelijker te begrijpen, omdat de tussenliggende boolean van een 'if' voorwaarde maakt het voornemen van de aandoening meer expliciet.
  • Als u met behulp van niet-standaard of onverwachte code, zoals logische operatoren op op boolean waarden, kunnen mensen veel gemakkelijker zien waarom je dit hebt gedaan.

EDIT: U didnt expliciet zegt dat je wilde dat de conditionele voor 'if' statements (hoewel dit lijkt het meest waarschijnlijk), dat was mijn veronderstelling. Maar mijn suggestie van een tussenliggende boolean staat nog steeds.

antwoordde op 24/08/2008 om 16:42
bron van user

stemmen
11

I denk

a != b

is wat je wilt

antwoordde op 29/08/2008 om 00:56
bron van user

stemmen
0

IIRC, zullen veel C ++ compilers waarschuwen bij een poging om het resultaat te werpen van een bitsgewijze bewerking als een bool. Je zou hebben om een ​​soort cast te gebruiken om de compiler gelukkig te maken.

Gebruik een bitsgewijze bewerking per if expressie zou hetzelfde kritiek dienen, hoewel misschien niet door de compiler. Any-zero niet-waarde wordt beschouwd als echte, dus iets als "if (7 & 3)" zal waar zijn. Dit probleem kan in Perl aanvaardbaar zijn, maar C / C ++ zijn zeer expliciet talen. Ik denk dat de Spock wenkbrauw is due diligence. :) Ik zou "== 0" of voeg "! = 0" om het volkomen duidelijk maken wat uw doel was.

Maar goed, het klinkt als een persoonlijke voorkeur. Ik zou de code door middel van lint of iets dergelijks te voeren en te kijken of het ook denkt dat het een onverstandige strategie. Persoonlijk, het leest als een codering fout.

antwoordde op 29/08/2008 om 01:08
bron van user

stemmen
24

Twee belangrijke redenen. Kortom, zorgvuldig te overwegen; zou er een goede reden voor zijn, maar als er zijn zeer expliciet in uw commentaar, omdat het bros kan worden en, zoals je zelf zegt, zijn mensen over het algemeen niet gewend aan code als volgt.

Bitwise XOR! = Logische XOR (met uitzondering van 0 en 1)

Ten eerste, als u werkt met uitzondering waarden falseen true(of 0en 1, als gehele getallen), de ^operator kan gedrag gelijk aan een logische xor voeren. Bijvoorbeeld:

int one = 1;
int two = 2;

// bitwise xor
if (one ^ two)
{
  // executes because expression = 3 and any non-zero integer evaluates to true
}

// logical xor; more correctly would be coded as
//   if (bool(one) != bool(two))
// but spelled out to be explicit in the context of the problem
if ((one && !two) || (!one && two))
{
  // does not execute b/c expression = ((true && false) || (false && true))
  // which evaluates to false
}

Met dank aan de gebruiker @Patrick voor het uiten van deze eerste.

Volgorde van bewerkingen

Ten tweede |, &en ^, als logische operatoren op, doe geen kortsluiting. Daarnaast meerdere logische operatoren op elkaar geketend in één overzicht - zelfs met expliciete haakjes - na te bestellen door optimalisatie, omdat alle 3 Normaliter worden commutatief. Dit is belangrijk als de volgorde van de werkzaamheden zaken.

Met andere woorden

bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false

zal niet altijd hetzelfde resultaat (of eindtoestand) als

bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler

Dit is vooral belangrijk omdat je niet methoden kunnen beheersen a()en b()of iemand anders kan langs komen en ze te veranderen later niet begrijpen van de afhankelijkheid en leiden tot een vervelende (en vaak los-build only) bug.

antwoordde op 29/08/2008 om 04:15
bron van user

stemmen
3

In tegenstelling tot Patrick's antwoord, C ++ heeft geen ^^operator voor het uitvoeren van een kortsluiting of uitsluitende. Als je erover nadenkt voor een tweede, met een ^^operator zou geen zin hoe dan ook te maken: met exclusieve of, het resultaat is altijd afhankelijk van beide operanden. Echter, Patrick's waarschuwing over niet- bool"Boolean" types geldt net zo goed bij het vergelijken 1 & 2aan 1 && 2. Een klassiek voorbeeld hiervan is de Windows GetMessage()-functie, die een tri-state terugkeert BOOL: nul is, 0of -1.

Met behulp van &in plaats van &&en |in plaats van het ||is geen ongewoon typo, dus als je met opzet doet het, het verdient een reactie te zeggen waarom.

antwoordde op 16/09/2008 om 04:54
bron van user

stemmen
5

Nadelen van de bitlevel operators.

Je vraagt:

“Is er een reden de logische operatoren op niet te gebruiken &, |en ^voor 'bool' waarden in C ++? ”

Ja, de logische operatoren , dat is de ingebouwde hoog niveau Booleaanse operatoren !, &&en ||bieden de volgende voordelen:

  • Gegarandeerd omzetting van argumenten aan bool, dat wil zeggen tot 0en 1ordinale waarde.

  • Gegarandeerd kortsluiting evaluatie wanneer de evaluatie van meningsuiting stopt zodra het eindresultaat bekend is.
    Dit kan worden geïnterpreteerd als een boom-waarde logica, met True , False en onbepaald .

  • Leesbare tekstuele equivalenten not, anden or, zelfs als ik ze niet zelf niet gebruiken.
    Als lezer Antimoon merkt in een reactie ook de bitlevel operators hebben alternatieve tokens, namelijk bitand, bitor, xoren compl, maar naar mijn mening zijn dit minder leesbaar is dan and, oren not.

Simpel gezegd, elk dergelijk voordeel van het hoge niveau operators is een nadeel van de bitlevel operators.

Met name omdat de logische operatoren op gebrek argument conversie naar 0/1 krijg je bijvoorbeeld 1 & 20, terwijl 1 && 2true. Ook ^kan bitsgewijze exclusieve of, zich misdragen op deze manier. Beschouwd als boolean waarden 1 en 2 zijn hetzelfde, namelijk true, maar beschouwd als bitpatronen ze zijn anders.


Hoe te uiten logische of / of in C ++.

U levert dan een beetje achtergrond voor de vraag,

“Ik heb soms lopen in situaties waar ik wil precies één van de twee voorwaarden waar (XOR), dus ik gooi alleen de ^ operator in een voorwaardelijke expressie.”

Welnu, de logische operatoren op hebben een hogere prioriteit dan de logische operatoren. Dit betekent met name dat in een gemengde uitdrukkingen zoals

a && b ^ c

krijg je het misschien onverwacht resultaat a && (b ^ c).

In plaats daarvan gewoon schrijven

(a && b) != c

uitdrukken meer bondig wat je bedoelt.

Voor de meervoudige argument of / of er is geen C ++ operator die het werk doet. Bijvoorbeeld, als je schrijft a ^ b ^ cdan dat is niet een uitdrukking die “ofwel zegt a, bof cis true”. In plaats daarvan zegt: “Er is een oneven aantal a, ben cwaar zijn”, die misschien wel 1 van hen of alle 3 de ...

Als u het algemene of / of bij het uiten a, ben czijn van het type bool, gewoon schrijven

(a + b + c) == 1

of, met niet- boolargumenten, ze converteren naar bool:

(!!a + !!b + !!c) == 1


Met behulp van &=naar boolean resultaten accumuleren.

U verder uit te werken,

“Ik moet ook Booleaanse waarden soms ophopen, en &=en |=?kan erg nuttig zijn.”

Nou, dit komt overeen met het controleren of respectievelijk al of enige voorwaarde is voldaan, en de Morgan wet vertelt u hoe om te gaan van de ene naar de andere. Dwz je hoeft alleen maar een van hen. Je zou in principe gebruik *=als een &&=-operator (voor zo goede oude George Boole ontdekt, logisch en kan heel gemakkelijk worden uitgedrukt als vermenigvuldiging), maar ik denk dat dat zou verwarren en misschien misleiden handhavers van de code.

Denk ook:

struct Bool
{
    bool    value;

    void operator&=( bool const v ) { value = value && v; }
    operator bool() const { return value; }
};

#include <iostream>

int main()
{
    using namespace std;

    Bool a  = {true};
    a &= true || false;
    a &= 1234;
    cout << boolalpha << a << endl;

    bool b = {true};
    b &= true || false;
    b &= 1234;
    cout << boolalpha << b << endl;
}

Output met Visual C ++ 11,0 en g ++ 4.7.1:

waar
vals

De reden voor het verschil in resultaten is dat de bitlevel &=een conversie niet te verstrekken aan boolhaar rechterzijde argument.

Dus, welke van deze resultaten doen u wenst voor het gebruik van &=?

In het eerste geval true, dan beter een operator (bijvoorbeeld zoals hierboven) of een benoemde functie te definiëren, of gebruik maken van een expliciete omzetting van de rechterkant meningsuiting, of schrijf de update volledig.

antwoordde op 21/12/2012 om 05:56
bron van user

stemmen
0

Gebruikt bitsgewijze bewerkingen voor bool bespaart onnodige aftakkingsvoorspellingsinformatie logische door de processor als gevolg van een 'CMP' instructie van logische bewerkingen gebracht.

Het vervangen van de logische met bitwise operaties (waar alle operands bool) genereert meer efficiënte code met hetzelfde resultaat. De efficiëntie moet idealiter alle kortsluiting voordelen de die kunnen worden ingezet in het bestelproces met behulp van logische bewerkingen te compenseren.

Dit kan code een beetje un-leesbaar te maken zij de programmeur moet reageren met redenen waarom het zo werd gedaan.

antwoordde op 26/04/2018 om 08:34
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more