Cosa significa: !!

Ciao,

sto seguendo una guida riguardante gli shift registers e spiega come è scritta la funzione shiftOut. Nella funzione vi è digitalWrite(dataPin, !!(val & (1 << i))); cosa sono i due punti esclamativi? A cosa servono?

Grazie in anticipo!

riporto la funzione:

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
int i;

for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));

digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}

è una doppia negazione, quindi è come non metterli...

Strano il doppio punto esclamativo non lo avevo incontrato mai. Il punto esclamativo è un'operatore logico. La sua funzione booleana e il not. Due not not equivalgono a due negazioni cioè !!(true) dovrebbe essere valutata come vera, mentre !(true) e valutata come false.

Non so aspettiamo un guru.

Ciao.

Non è come non metterlo... ha un suo significato! Non dimentichiamo che "!" è il not booleano, l'operatore logico not è "~". Ciao

MGuruDC:
Non è come non metterlo… ha un suo significato!
Non dimentichiamo che “!” è il not booleano, l’operatore logico not è “~”.
Ciao

non ti seguo. appunto perché è booleano, ! ritorna vero solo se (val & (1 << i)) è falso, ovvero == 0. poi lo ritrasforma in falso col secondo !, ma già in partenza vero e falso erano già riconoscibili. Anzi stessa cosa sarebbe avvenuta col doppio ~~, l’operazione restituiva false solo se il valore di partenza era B00000000, ovvero 0, ovvero “falso”.

Magari mi sfugge qualcosa, se è così mi fa piacere saperlo.

Nono, sono diversi…
!170 = 0, perché “!” capisce solo se il suo argomento e uguale o diverso da zero, poi lo inverte.
~170 = 85, perché “~” prende ogni singolo bit del suo argomento e lo inverte, quindi 1010 - 1010 diventa 0101 - 0101

Quel “!!”… fa un semplice cast, e si assicura che il valore restituito da tutta l’espressione sia esattamente 1 oppure 0 e mai 2, 4, 8 ecc che risulterebbero da val & (1 << i).
Ciao

Allora il !! ti restituisce 0 o 1 e non 0 e un numero tra 1 e 255. Alla fine tutta l' espressione scandisce la variabile e segna ogni bit se é 1 o 0. Ciao Uwe

!170 = 0, perché "!" capisce solo se il suo argomento e uguale o diverso da zero, poi lo inverte. ~170 = 85, perché "~" prende ogni singolo bit del suo argomento e lo inverte, quindi 1010 - 1010 diventa 0101 - 0101

ok, ci sono e ti do parzialmente ragione, ma visto che la funzione digitalWrite prende in input un booleano, sia che usi ! o ~ la storia non cambia. Un numero != 0 non rimmarrà mai != 0 e un lo 0 non rimarrà mai tale.

In oltre il C definisce false un qualsiasi valore == 0 e tutto il resto true, quindi cade anche il discorso:

Allora il !! ti restituisce 0 o 1 e non 0 e un numero tra 1 e 255. Alla fine tutta l' espressione scandisce la variabile e segna ogni bit se é 1 o 0. Ciao Uwe

Al fine funzionale (e secondo me anche di lettura) del programma quel !! è un incasinazione inutile

Al fine funzionale (e secondo me anche di lettura) del programma quel !! è un incasinazione inutile

Può essere che il cast eplicito !! risulti più rapido del cast implicito che si ha se passi un intero ad una variabile di tipo bool.

Abbiamo imparato un'altra cosa.

Ciao.

Quel "~" lo avevo tirato fuori solo per far riflettere bene su come opera il suo amico "!", Il metodo di flameman è assolutamente migliore, proporrei di aggiornare la libreria con il suo metodo, ma il realtà penso che questa sega mentale del "!!" sia retaggio di qualche vecchia implementazione del digitalWrite, che in nome della velocità di calcolo richiedeva attenzione sul valore dato in ingresso... A quanto vedo ora il problema non c'è più perché lo stato della porta viene deciso con un if-else e il lavoro del "!!" viene rifatto ogni volta a valle di tutto. Conclusione: con la digitalWrite che usiamo adesso quel "!!" si può togliere. Ciao

Ciao,

innanzitutto grazie. Poi vorrei specificare che non so quanto vecchio sia il tutorial ma magari la libreria è stata già aggiornata. In definitiva il !! è difficile da leggere magari poco elegante ma è una soluzione veloce giusto?

Ok allora non è neanche la maniera più veloce quindi forse bisognerebbe controllare se la funzione è stata o meno modificata.

In realtà nella guida che sto seguendo si cerca di velocizzare il più possibile l'uso dei registri di shift. Immagino, quindi, che la modifica da te proposta possa essere funzionale all'obiettivo.

http://www.picano.nl/microcontrollers/arduino/control-many-leds-with-pwm