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: