Perché '&&' e non '&'?


135

Perché è &&preferibile &e ||preferibile |?

Ho chiesto a qualcuno che stava programmando da anni e la sua spiegazione era:

Ad esempio, in if (bool1 && bool2 && bool3) { /*DoSomething*/ }, bool1deve essere vero per testarlo, bool2che deve essere vero prima di passare a bool3, ecc. Se avessi usato un singolo &invece non c'è alcun ordine per il test, anche se tutti devono essere fedeli a passare alla riga successiva, quindi perché importa comunque?

Nota: vorrei sottolineare che sono l'equivalente di programmazione di un bambino e questa non è una domanda seria o urgente. È più una questione di capire perché le cose dovrebbero essere fatte in un certo modo piuttosto che in un altro.


55
& and && | e || sono operatori completamente diversi
Felice Pollano,

3
Contrassegnato, poiché questo non si applica solo a C #
Jonathan Dickinson,

12
Ripristinato, perché le risposte sono già specifiche di C # e il funzionamento interno potrebbe differire un po 'in altre lingue che hanno generalmente lo stesso concetto.
Daniel Hilgarth,

8
@Felice: sono diversi, ma quasi completamente diversi. Sono in effetti molto simili: x & ye x && yvaluteranno sempre allo stesso risultato se xey sono espressioni di tipo booleano. In effetti l'unica differenza in quel caso sembra essere quella in x & y, y viene sempre valutata.
Joren,

1
@slawekin: suggerirei di leggere le risposte. Alcuni scrivono ampiamente sulle differenze di prestazioni. La risposta potrebbe sorprenderti però.
Abel,

Risposte:


183

Nella maggior parte dei casi, &&e ||sono preferiti rispetto &e |perché i primi sono in corto circuito, il che significa che la valutazione viene annullata non appena il risultato è chiaro.

Esempio:

if(CanExecute() && CanSave())
{
}

Se CanExecuterestituisce false, l'espressione completa sarà false, indipendentemente dal valore restituito di CanSave. Per questo motivo, CanSavenon viene eseguito.

Questo è molto utile nelle seguenti circostanze:

string value;
if(dict.TryGetValue(key, out value) && value.Contains("test"))
{
    // Do Something
}

TryGetValueritorna falsese la chiave fornita non viene trovata nel dizionario. A causa della natura di cortocircuito di &&, value.Contains("test")viene eseguito solo quando TryGetValueritorna truee quindi valuenon lo è null. Se invece si utilizzasse l' operatore AND bit a bit& , si otterrebbe un NullReferenceExceptionse la chiave non viene trovata nel dizionario, poiché la seconda parte dell'espressione viene comunque eseguita.

Un esempio simile ma più semplice di questo è il seguente codice (come menzionato da TJHeuvel):

if(op != null && op.CanExecute())
{
    // Do Something
}

CanExecuteviene eseguito solo in caso opcontrario null. In optal caso null, la prima parte dell'espressione ( op != null) viene valutata falsee la valutazione del resto ( op.CanExecute()) viene ignorata.

Oltre a questo, tecnicamente, sono diverse, anche:
&&e ||può essere utilizzato solo su boolconsiderando &e |può essere utilizzato su qualsiasi tipo integrale ( bool, int, long, sbyte, ...), perché sono operatori bit per bit. &è il operatore AND bit a bit ed |è l' operatore OR bit a bit .

Per l'esattezza, in C #, quegli operatori ( &, |[e^ ]) sono chiamati "Operatori logici" (vedere le specifiche di C # , capitolo 7.11). Esistono diverse implementazioni di questi operatori:

  1. Per gli interi ( int, uint, longeulong , capitolo 7.11.1):
    Vengono implementati per calcolare il risultato bit degli operandi e l'operatore, cioè &è attuare per calcolare il bit logico ANDetc.
  2. Per le enumerazioni (capitolo 7.11.2):
    sono implementate per eseguire l'operazione logica del tipo sottostante dell'enumerazione.
  3. Per bool e bool nulla (capitoli 7.11.3 e 7.11.4):
    il risultato non viene calcolato usando calcoli bit a bit. Il risultato è sostanzialmente cercato in base ai valori dei due operandi, perché il numero di possibilità è così piccolo.
    Poiché entrambi i valori vengono utilizzati per la ricerca, questa implementazione non è in corto circuito.

31
Questo può anche essere utile per verificare se qualcosa è nullo. Ad esempio: if(op != null && op.CanExecute()). Poiché la seconda causa non viene valutata quando la prima non è vera, questo è valido.
TJHeuvel,

2
@TJHeuvel: Questo è sostanzialmente lo stesso utilizzo che ho descritto con il mio TryGetValueesempio. Ma sì, è un altro buon esempio di questo.
Daniel Hilgarth,

4
Buona risposta. Forse dovresti anche aggiungere un esempio di come &o |viene usato con argomenti non bool (ovvero cosa fanno gli operatori) a beneficio di tutte le persone nuove.
Zabba,

81

Spiegare chiaramente cosa significhi (anche se le altre risposte suggeriscono - ma probabilmente usa una terminologia che non capisci).

Il seguente codice:

if (a && b)
{
   Foo();
}

È davvero compilato per questo:

if (a)
{
    if (b)
    {
        Foo();
    }
}

Dove il seguente codice viene compilato esattamente come è rappresentato:

if (a & b)
{
   Foo();
}

Questo si chiama corto circuito. In generale dovresti sempre usare &&e ||nelle tue condizioni.

Segni bonus: c'è uno scenario in cui non dovresti. Se ci si trova in una situazione in cui le prestazioni sono cruciali (e questo è nano-secondi cruciale ) utilizzare il corto circuito solo quando è necessario (ad es. nullControllo) - poiché un cortocircuito è un ramo / salto; che potrebbe provocare un errore di filiale nella CPU; una &è molto più economico &&. C'è anche uno scenario in cui il corto circuito può effettivamente rompere la logica: dai un'occhiata a questa mia risposta .

Diatriba / Monologo : per quanto riguarda la cattiva previsione del ramo che più felicemente ignora. Citando Andy Firth (che ha lavorato ai giochi per 13 anni): "Potrebbe trattarsi di un livello inferiore a cui la gente pensa di dover andare ... ma si sbaglierebbe. Comprendere come l'hardware che stai programmando per i rami di cura può influenzare le prestazioni in misura ENORME ... molto più di quanto la maggior parte dei programmatori possa apprezzare in merito alla morte di mille tagli ".

  • Gli sviluppatori di giochi (e altri che lavorano in condizioni estreme in tempo reale) arrivano fino a ristrutturare la loro logica per adattarsi meglio al predittore. Ci sono anche prove di ciò nel codice mscorlib decompilato.
  • Solo perché .NET ti protegge da questo tipo di cose non significa che non sia importante. Una cattiva previsione del ramo è orribilmente costosa a 60 Hz; o a 10.000 richieste / secondo.
  • Intel non avrebbe strumenti per identificare la posizione delle previsioni errate, né Windows avrebbe un contatore delle prestazioni per questo, né ci sarebbe una parola per descriverlo, se non fosse un problema.
  • L'ignoranza sui livelli inferiori e sull'architettura non fa sbagliare qualcuno che ne sia consapevole.
  • Cerca sempre di capire i limiti dell'hardware su cui stai lavorando.

Ecco un punto di riferimento per i non credenti. È meglio eseguire il processo in tempo reale / alto per mitigare l'effetto dello scheduler: https://gist.github.com/1200737


7
A proposito dei "punti bonus": conosciamo tutti il ​​bene che deriva dall'ottimizzazione prematura. :)
un CVn

6
@Michael - ecco perché 'nano-secondi cruciali' è in grassetto :). Gli sviluppatori di giochi AAA in genere si preoccupano di cose come questa - e non si sa mai chi leggerà le risposte; quindi è sempre meglio documentare anche i casi limite / estremi.
Jonathan Dickinson,

1
Quel punteggio bonus è valido per C #? Non avrei pensato, come viene interpretato MSIL, a meno che l'espressione non sia stata compilata fino al codice macchina.
Jeremy McGee,

7
@Jeremy MSIL non viene interpretato.
Jonathan Dickinson,

2
@TheD ricontrolla la risposta - Ho aggiunto un monologo sul motivo per cui DOVREBBE preoccuparti di questo. E, FYI, si (x && y)traduce in LOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;dove si (x & y)traduce LOAD x; LOAD y; AND; BRANCH_FALSE;. Un ramo contro due.
Jonathan Dickinson,

68

Operatore logico ( ||e &&) vs. operatore bit per bit ( |e &).

La differenza più cruciale tra un operatore logico e un operatore bit a bit è che un operatore logico prende due valori booleani e produce un valore booleano mentre un operatore bit a bit prende due numeri interi e produce un numero intero (nota: numeri interi indica qualsiasi tipo di dati integrale, non solo int).

Per essere pedante, un operatore bit a bit prende un modello di bit (ad esempio 01101011) e fa un AND / OR bit per bit su ogni bit. Ad esempio, se hai due numeri interi a 8 bit:

a     = 00110010 (in decimal:    32+16+2   = 50)
b     = 01010011 (in decimal: 64+   16+2+1 = 83)
----------------
a & b = 00010010 (in decimal:       16+2   = 18)
a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)

mentre un operatore logico lavora solo in bool:

a      = true
b      = false
--------------
a && b = false
a || b = true

In secondo luogo, è spesso possibile utilizzare un operatore bit a bit su bool poiché true e false sono rispettivamente equivalenti a 1 e 0, e succede che se si traducono true in 1 e false in 0, quindi si eseguono operazioni bit a bit, quindi si converta un valore diverso da zero a vero e zero a falso; succede che il risultato sarà lo stesso se avessi appena usato un operatore logico (controlla questo per l'esercizio).

Un'altra importante distinzione è anche che un operatore logico è in corto circuito . Pertanto, in alcuni ambienti [1], spesso vedi persone che fanno qualcosa del genere:

if (person && person.punch()) {
    person.doVictoryDance()
}

che si traduce in: "se la persona esiste (cioè non è nulla), prova a dargli un pugno, e se il pugno ha successo (cioè restituisce vero), allora fai una danza della vittoria" .

Se avessi usato invece un operatore bit per bit, questo:

if (person & person.punch()) {
    person.doVictoryDance()
}

si tradurrà in: "se la persona esiste (cioè non è nulla) e il pugno ha successo (cioè restituisce vero), allora fai una danza della vittoria" .

Si noti che nell'operatore logico in cortocircuito, il person.punch()codice potrebbe non essere eseguito affatto se personè nullo. In effetti, in questo caso particolare, il secondo codice produrrebbe un errore di riferimento null se personè null, poiché tenta di chiamare person.punch()indipendentemente dal fatto che la persona sia null o meno. Questo comportamento di non valutazione dell'operando corretto si chiama corto circuito .

[1] Alcuni programmatori si affrettano a mettere una chiamata di funzione che ha un effetto collaterale all'interno di ifun'espressione, mentre per altri è un linguaggio comune e molto utile.

Poiché un operatore bit a bit lavora su 32 bit alla volta (se si utilizza una macchina a 32 bit), può portare a un codice più elegante e più veloce se è necessario confrontare un numero enorme di condizioni, ad es.

int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3,
    CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6;

Person person;
person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS;

Place bar;
bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK;

Place military;
military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT;

CurrentLocation cloc1, cloc2;
cloc1.usable_abilities = person_abilities & bar_rules;
cloc2.usable_abilities = person_abilities & military_rules;

// cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT`
// while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`

Fare lo stesso con gli operatori logici richiederebbe una quantità scomoda di confronti:

Person person;
person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true;
person.can_shoot_cannons = false;

Place bar;
bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true;
bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false;

Place military;
military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true;
military.rules.can_drink = military.rules.can_talk = false;

CurrentLocation cloc1;
bool cloc1.usable_abilities.can_punch         = bar.rules.can_punch         && person.can_punch,
     cloc1.usable_abilities.can_kick          = bar.rules.can_kick          && person.can_kick,
     cloc1.usable_abilities.can_drink         = bar.rules.can_drink         && person.can_drink,
     cloc1.usable_abilities.can_sit           = bar.rules.can_sit           && person.can_sit,
     cloc1.usable_abilities.can_shoot_guns    = bar.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons
     cloc1.usable_abilities.can_talk          = bar.rules.can_talk          && person.can_talk;

bool cloc2.usable_abilities.can_punch         = military.rules.can_punch         && person.can_punch,
     cloc2.usable_abilities.can_kick          = military.rules.can_kick          && person.can_kick,
     cloc2.usable_abilities.can_drink         = military.rules.can_drink         && person.can_drink,
     cloc2.usable_abilities.can_sit           = military.rules.can_sit           && person.can_sit,
     cloc2.usable_abilities.can_shoot_guns    = military.rules.can_shoot_guns    && person.can_shoot_guns,
     cloc2.usable_abilities.can_talk          = military.rules.can_talk          && person.can_talk,
     cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;

Un esempio classico in cui vengono utilizzati schemi di bit e operatore bit per bit è nelle autorizzazioni del file system Unix / Linux.


3
+1 per il lato riguarda il problema. Sorpreso, non è stato menzionato prima
Conrad Frix il

3
l'esempio sembra un po 'violento, ma sembra che altre risposte si concentrino troppo sul corto circuito e non abbastanza sulla differenza tra operare su numeri interi e su valori booleani.
R0MANARMY,

La funzione deve essere compresa prima che entrino in gioco i dettagli dell'implementazione (corto circuito / effetti collaterali). Sono contento che tu abbia chiarito la differenza principale tra logica booleana e intera, non cortocircuito.
Abel,

@ROMANARMY - violento, adoro l'ironia data al tuo monkiker. Bel lavoro
brumScouse

8

In caso di:

if (obj != null && obj.Property == true) { }

funzionerebbe come previsto.

Ma:

if (obj != null & obj.Property == true) { }

potrebbe potenzialmente generare un'eccezione di riferimento null.


2

Breve e semplice:

1 && 2= vero
perché
1 = vero (diverso da zero) in C
2 = vero (diverso da zero) in C

trueANDS logicamente con trueda dare true.

Ma

1 & 2= 0 = falso
perché
1 = 0001 in binario
2 = 0010 in binario

0001 AND bit a bit con 0010 per fornire 0000 = 0 in decimale.

Allo stesso modo per || e | anche gli operatori ...!


2
-1: Stiamo parlando di C # qui ... 1 && 2è illegale in C #
Daniel Hilgarth il

Ma questo è un esempio estremamente importante che spiega perché non puoi semplicemente scambiare & e && (che molte persone sembrano pensare).
bobobobo,

1

&&è la versione di corto circuito di &.

Se stiamo valutando false & true, sappiamo già dal primo argomento che il risultato sarà falso. La &&versione dell'operatore restituirà un risultato il più presto possibile, anziché valutare l'intera espressione. V'è anche una simile verion del |gestore, ||.


1
if (list.Count() > 14 && list[14] == "foo")

è salvo

if (list.Count() > 14 & list[14] == "foo")

andrebbe in crash se l'elenco non ha le dimensioni giuste.


Non riesco a immaginare che qualcuno possa scrivere "if (list.Count ()> 14 & list [14] ==" foo ")" invece di "if (list.Count ()> 14 && list [14] ==" foo ")". e in questo caso non è possibile utilizzare semplicemente e naturalmente per && anche se 'è sicuramente sicuro (elenco [1] per esempio).
Tien Do,

1

Gli operatori C # dovrebbero spiegare perché:

Essenzialmente avere due &o due |significa che è un condizionale piuttosto che un logico, quindi puoi dire la differenza tra i due.

& Operator ha un esempio dell'uso di uno&.


Entrambi i collegamenti sono (effettivamente) interrotti (reindirizza a "Documentazione ritirata di Visual Studio 2005" ).
Peter Mortensen,

1

OK, sul valore nominale

    Boolean a = true;
    Boolean b = false;

    Console.WriteLine("a({0}) && b({1}) =  {2}", a, b, a && b);
    Console.WriteLine("a({0}) || b({1}) =  {2}", a, b, a || b);
    Console.WriteLine("a({0}) == b({1}) =  {2}", a, b, a == b);

    Console.WriteLine("a({0}) & b({1}) =  {2}", a, b, a & b);
    Console.WriteLine("a({0}) | b({1}) =  {2}", a, b, a | b);
    Console.WriteLine("a({0}) = b({1}) =  {2}", a, b, a = b);

produce la stessa risposta. Tuttavia, come hai mostrato, se hai una domanda più complessa, allora:

if (a and b and c and d) ..

Se anon è vero e forse bè una funzione in cui deve spegnersi, connettersi a qualcosa, ottenere questo, farlo, prendere una decisione .. perché preoccuparsi? Perdita di tempo, si sa che è già fallito. Perché spegnere la macchina e fare un lavoro extra inutile?

L'ho sempre usato &&perché ho messo più probabilità di fallire prima, ergo, meno calcoli prima di andare avanti quando non ha senso. Se non è possibile prevedere scelte meno probabili, ad esempio se si dispone di un valore booleano per limitare l'output di dati, ad esempio:

if (limit && !MyDictionary.ContainsKey("name")) 
    continue;

In caso contrario limit, non preoccuparti di controllare la chiave, che potrebbe richiedere più tempo ...


1

Se utilizzato in un'espressione logica come un'istruzione if &&preferibile perché interromperà la valutazione delle espressioni non appena si incontra il primo falso risultato. Ciò è possibile perché un valore falso farà sì che l'intera espressione sia falsa. Allo stesso modo (e di nuovo nelle espressioni logiche) ||è preferibile perché smetterà di valutare le espressioni non appena incontra un'espressione vera perché qualsiasi valore vero farà sì che l'intera espressione sia vera.

Se tuttavia le espressioni che vengono organizzate o elaborate insieme hanno effetti collaterali e vuoi che tutto ciò avvenga come risultato della tua espressione (indipendentemente dal risultato dell'espressione logica), allora &e |potrebbe essere usato. Al contrario, gli operatori &&e ||possono essere utili come guardie contro gli effetti collaterali indesiderati (come un puntatore nullo che provoca il lancio di un'eccezione).

Gli operatori &e |possono anche essere usati con numeri interi e in questo caso producono un risultato intero che è i due operandi e-ed o o-ed insieme a livello di bit. Ciò può essere utile quando i bit binari di un valore intero vengono utilizzati come una matrice di valori veri e falsi. Per verificare se un determinato bit è attivato o disattivato, una maschera di bit viene bit per bit ed-ed con il valore. Per attivare un po ', la stessa maschera può essere bit per bit o ed ed con il valore. Infine, per disattivare un po ', il complemento bit per bit (usando ~) di una maschera viene bit per bit ed ed ed con il valore.

int a = 0; // 0 means all bits off
a = a | 4; // set a to binary 100
if ((a & 4) != 0) {
    // will do something
}
a = a & (~4) // turn bit off again, a is now 000

In lingue diverse da C #, è necessario prestare attenzione con le modalità logica e bit per bit di & e |. Nel codice sopra, l' ifespressione condizionale dell'istruzione (a & 4) != 0è un modo sicuro per esprimere questa condizione, ma in molti linguaggi simili a C, le istruzioni condizionali possono semplicemente trattare i valori interi zero come valori interi falsi e diversi da zero come veri. (Il motivo di ciò si riferisce alle istruzioni del processore del ramo condizionale disponibili e alla loro relazione con il flag zero che viene aggiornato dopo ogni operazione di numero intero.) Quindi il ìftest dell'istruzione per zero può essere rimosso e la condizione potrebbe essere abbreviata (a & 4).

Ciò potrebbe causare confusione e forse persino problemi quando le espressioni si combinano usando i valori di ritorno bit per bit e operatore che non hanno bit allineati. Considera il seguente esempio in cui sono desiderati gli effetti collaterali di due funzioni, prima di verificare che entrambi abbiano avuto successo (come definito da loro che restituiscono un valore diverso da zero):

if (foo() & bar()) {
    // do something
}

In C, se foo()restituisce 1 e bar()restituisce 2, il "qualcosa" non verrà eseguito perché 1 & 2è zero.

C # richiede istruzioni condizionali come ifavere un'opranda booleana e il linguaggio non consente di trasmettere un valore intero a un valore booleano. Quindi il codice sopra genererebbe errori del compilatore. Sarebbe più correttamente espresso come segue:

if (foo() != 0 & bar() != 0) {
    // do something
}

1

Se sei un programmatore C di vecchia data, fai attenzione . C # mi ha davvero sorpreso.

MSDN dice per l' |operatore:

Binario | gli operatori sono predefiniti per i tipi integrali e bool . Per tipi integrali, | calcola l'OR bit a bit dei suoi operandi. Per gli operandi bool | calcola l'OR logico dei suoi operandi; cioè, il risultato è falso se e solo se entrambi i suoi operandi sono falsi.

(L'enfasi è mia.) I tipi booleani sono gestiti in modo speciale, e in questo contesto la domanda inizia a dare un senso, e la differenza è, come altri già affermati nelle loro risposte:

&&e ||sono in corto circuito. &e |valutare entrambi gli operandi.

e ciò che è preferibile dipende da molte cose come effetti collaterali, prestazioni e leggibilità del codice, ma generalmente gli operatori di corto circuito sono preferibili anche perché sono meglio compresi da persone con un background simile come me.

Il motivo è: vorrei argomentare in questo modo: dal momento che non esiste un vero tipo booleano in C, è possibile utilizzare l'operatore bit per bit |e fare in modo che il suo risultato venga valutato come veritiero o falso in una condizione if. Ma questo è l'atteggiamento sbagliato per C #, perché esiste già un caso speciale per i tipi booleani.


0

È importante, perché se il costo della valutazione di bool2 (ad esempio) è elevato ma bool1 è falso, allora ti sei risparmiato un bel po 'di calcolo usando && over & &


0

Perché &&e ||sono usati per il controllo del flusso proprio come lo if/elsesono. Non si tratta sempre di condizionali. È perfettamente ragionevole scrivere come una dichiarazione, non come una ifo una whilecondizione, quanto segue:

 a() && b() && c() && d();

o anche

 w() || x() || y() || z();

Non è solo che quelli sono più facili da scrivere rispetto alle if/elseversioni equivalenti ; sono anche molto più facili da leggere e comprendere.


0

&& e & significano due cose molto diverse e ti danno due risposte diverse.

1 && 2restituisce 1 ("vero")
1 & 2restituisce 0 ("falso")

&&è un operatore logico - significa "vero se entrambi gli operandi sono veri"
&è un confronto bit a bit. Significa "dimmi quale dei bit è impostato in entrambi gli operandi"


2
La domanda riguarda C #. In C #, non c'è modo di lanciare un numero su un bool, quindi 0 non è "falso" e diverso da zero non è "vero"; semplicemente non c'è equivalenza.
Nate CK,

Per convertire il numero in bool, in modo che 1 significhi vero e 0 significhi falso, dì "n! = 0" (suppongo ... non ho molta familiarità con C #). In realtà volevo ritirare questo commento poiché non è ben studiato e non penso sia utile o molto pertinente al commento precedente ora che ci penso di più, ma ho accidentalmente premuto invio e ora non penso di poterlo fare cancellalo così eccoti, per quello che vale :-)
Don Hatch l'

1 && 2fornisce un errore del compilatore: "Errore 4 L'operatore '&&' non può essere applicato agli operandi di tipo 'int' e 'int'"
Peter Mortensen,

0

Il modo più rapido (e leggermente attenuato) di spiegarlo alle persone che NON DEVONO conoscere le esatte operazioni del codice quando lo fanno è

&& sta controllando ciascuna di queste condizioni fino al a non trova un falso e restituisce l'intero risultato come falso

|| sta effettuando un controllo su ciascuna di queste condizioni fino al a non trova un vero e restituisce l'intero risultato come vero.

& sta facendo apon MATHS ENTRAMBI / TUTTE le condizioni e gestendo il risultato.

|sta facendo apon MATHS ENTRAMBI / TUTTE le condizioni e si occupa del risultato.

Non ho mai incontrato un punto in cui ho dovuto usare & o | all'interno di un'istruzione if. Lo uso principalmente per tagliare i valori esadecimali nei colori dei suoi componenti usando lo spostamento bit a bit.

PER ESEMPIO:

r = fullvalue >> 0xFF & 0xFF;
g = fullvalue >> 0xF & 0xFF;
b = fullvalue & 0xFF;

All'interno di questa operazione "& 0xFF" sta forzando a guardare solo il valore binario. Non ho trovato personalmente un uso per | ma comunque.


0

Semplicemente,

if exp1 && exp2

se exp1 è flase non , controlla exp2

ma

if exp1 & exp2

se exp1 è falseOrtrue controlla exp2

e raramente le persone usano &perché raramente vogliono controllare exp2 se exp1 lo èfalse

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.