differenze tra != e =!

stavo buttando giu uno sketch e ho scritto =!, e lo sketch non andava.

l'ho cambiato con != e andava.

allora cosa significa "=!" ?

boschi:
allora cosa significa "=!" ?

"=!" non è un operatore valido in C/C++, sicuramente avrgcc ha generato una warning però normalmente l'IDE di Arduino non le fa vedere e va a sapere come l'ha interpretato il compilatore.
Siamo allo stesso livello di "=" invece di "==" per l'eguaglianza, "=" viene compilato, con warning, però poi il controllo restituisce sempre true perché è una assegnazione e non un paragone.

Nelle nuove versioni dell'IDE si può impostare, tra le opzioni, anche il livello di "verbose" riguardo ai Warninga.
Di solito lo imposto su ALL e spunto anche l'output dettagliato per la compilazione e l'upload. Ma sono scelte personali.

PaoloP:
Nelle nuove versioni dell'IDE si può impostare, tra le opzioni, anche il livello di "verbose" riguardo ai Warninga.

L'avevo provato appena disponibile, però mi si impallava sempre la compilazione pertanto ho deselezionato la voce relativa, non ho più provato per vedere se adesso funziona.

Perdonatemi, ma temo che le vostre risposte siano poco comprensibili nella pratica, per qualcuno che pone una domanda come questa :roll_eyes:.

!= vuol dire diverso da, l'avrai capito ormai.

=! invece non è un operatore valido nel suo insieme, ma è composto da due operatori distinti: =, che permette di assegnare un valore a una variabile, e !, che serve a negare quel che segue, a livello logico (vero diventa falso, e viceversa).

All'interno di un if, il primo è sicuramente corretto:

if (a != 5) {
  // ...
}

Il secondo può esserlo, se si sa quel che si sta facendo:

if ((a = !b)) {
  // Qua dentro si entra solo se a è vero, ovvero solo se b è falso
}

Nota appunto le doppie parentesi, che servono a dire al compilatore che si sa quel che si sta facendo ;).

Spero che sia un po' più chiaro, ma nella pratica: scordati di =! :D.

1 Like

Ho qualche dubbio su questo punto.

=! vuol dire diverso da e qui siamo d'accordo
quindi

if (a != b) {codice}

esegue {codice} se a è diverso da b

e fino a qui siamo d'accordo.

Passiamo al secondo pezzo:

vorrei capire cosa fa il blocco

(a =!b)

che metti come condizione dell'if, anche se con doppie parentesi

secondo me è una assegnazione e pone a uguale a !b quindi se b è falso, a è vero e viceversa, ma rimane una assegnazione quindi restituisce sempre true indipendentemente da quanto valga b

invece

(a == !b)

confronta a con !b quindi è vero se a è vero e b è falso oppure a è falso e b è vero altrimenti è falso se a e b sono entrambi veri o entrambi falsi

vorrei capire dove sbaglio

Tutto giusto, eccetto questo:

secondo me è una assegnazione e pone a uguale a !b quindi se b è falso, a è vero e viceversa, ma rimane una assegnazione quindi restituisce sempre true indipendentemente da quanto valga b

Un'assegnazione non restituisce sempre true (non capisco perché, ma questa convinzione pare molto diffusa!), "restituisce" invece il valore dell'operando più a sinistra, per cui nel caso citato, quello di a. Per questo ho scritto:

if ((a = !b)) {
  // Qua dentro si entra solo se a è vero, ovvero solo se b è falso
}

PS: Occhio però che il primo =! che hai scritto nel tuo ultimo post dovrebbe essere != :D.

... uhm ... secondo me, a = !b , si limita ad assegnare ad a l'inverso di b ... mentre a == !b, controlla che a sia l'inverso di b ... dov'e' l'errore ?

Precisamente, non c'è nessun errore! Se poi quanto viene eseguito corrisponda o meno all'intenzione del programmatore, è tutto da verificare...

Uhm, aspetta ... a meno che a e b non contengano valori diversi da 0 ed 1 ... noi stiamo dando per scontato che li si usi su delle boleane TRUE e FALSE ... ma che succede se ad a o b era assegnato un valore diverso, o un float, o una tensione, o il valore di un PWM ?

Suppongo (ma non ne sono sicuro al 100%) che l'intero valore binario della variabile (secondo come e' stata dichiarata nel setup) venga invertito ... quindi ad esempio, nel caso di a = !b , se b fosse byte, che puo andare da 0 a 254, in teoria a dovrebbe invertirsi proporzionalmente (0 -> 254, 50-> 204, 250 -> 4, e cosi via) ... ma nel caso di un float non unsigned, ad esempio, -123.4 ? ... il compilatore lo tratterebbe nello stesso modo ?

Etemenanki:
Uhm, aspetta ... a meno che a e b non contengano valori diversi da 0 ed 1 ...

Per il C, 0 sempre falso qualsiasi valore diverso da 0 è vero, non solo 1. Quindi anche 123 è vero

Etemenanki:
Suppongo (ma non ne sono sicuro al 100%) che l'intero valore binario della variabile (secondo come e' stata dichiarata nel setup) venga invertito ... quindi ad esempio, nel caso di a = !b , se b fosse byte, che puo andare da 0 a 254, in teoria a dovrebbe invertirsi proporzionalmente (0 -> 254, 50-> 204, 250 -> 4, e cosi via) ... ma nel caso di un float non unsigned, ad esempio, -123.4 ?

No, come già detto da nid69ita, 0 è falso, TUTTO IL RESTO è vero. Poi di fatto gli operatori logici del C sono garantiti restituire sempre o 0 o 1. Ma occhio che non tutte le funzioni ritornano valori "logici", vedi ad esempio svariate implementazioni di isalpha() e compagnia. Temo comunque che stiamo entrando troppo nel tecnico :).

Tutto questo ha senso perché stiamo parlando di !, che è l'operatore che fa la negazione logica. In C esiste anche un operatore di negazione bitwise, che invece fa quello che dici tu, ed è ~ (ma dubito funzioni sui float). Ad esempio:

~0x0F == 0xF0

Mentre:

!0x0F == 0
!(!0x0F) == 1

Quest'ultimo trucchetto, viene a volte utilizzato per ottenere un valore strettamente booleano da un intero o simile, per quanto nutra dubbi sulla sua effettiva utilità.

Per completezza:

~(~0x0F) == 0x0F;

@SukkoPera:
Poi di fatto !0 restituirà sempre 1, ma è sbagliato fare affidamento su questo.

Perchè è sbagliato farci affidamento?
La conversione numerica in booleano tramite la doppia negazione è usatissima nel mondo della programmazione.
Esempio dato che non esiste l'xor logico per implementarlo basta scrivere:

if ( (!!A) ^ (!!B) )

ma anche per sommare, insomma viene spesso usato.

Riguardo al not bitwise invece viene spesso usato per assegnare il numero massimo di una variabile:

byte var = ~0;

vbextreme:
Perchè è sbagliato farci affidamento?

Hai ragione, ho fatto un po' di casino: !0 è garantito che sia 1. Credevo che lo standard garantisse solo che ritornasse un qualunque valore vero, e che questo "solitamente" fosse 1 per mera convenzione, ma mi sbagliavo. Ora correggo i post precedenti.

vbextreme:
Riguardo al not bitwise invece viene spesso usato per assegnare il numero massimo di una variabile:

byte var = ~0;

Occhio che però questo funziona solo con variabili unsigned!

Scusate se non hi risposto prima, normalmente le mail mi vengono notificate su android, stavolta non è stato cosí.

In parole estremamente povere in quel caso era sbagliato, domani poi mi leggo bene le risposte che mi avete dato, l'argomento inizia a intrigarmi :smiley: