# How shiftOut function works internally? (explanation on source code)

I were examining `shiftOut()` function code in `wiring_shift.c` and I didn't quite understand what is going in digitalWrite function. I see `!!(val & (1 << i))` is taking the bit value from `val` but how exactly it works?

The whole function is below.

``````void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t 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);
}
}
``````
• `!!(val & (1 << i))` is the most complex part of this code. If you do understand this, then what is the part you do not understand? Jun 1 '15 at 8:56
• @edgar-bonet Actually this was the question. I can see it somehow calculates the bit value, but I didn't understand how it do this. Jun 1 '15 at 9:01
• You do understand the behaviour of the shiftOut function? I mean, you do understand that it'll `shift out` a value (in binary form). And will give a clock pulse along with it.
– Paul
Jun 1 '15 at 10:29

I'll assume `bitOrder == LSBFIRST`.

• `i` is the bit number, i.e. the “index” of the next bit to write
• `1` is `00000001` in binary
• `<<` is the shift left operator. It returns its first argument shifted left by as many positions as indicated by the second argument
• `1<<i` is binary `00000001` shifted left by `i` positions, i.e. something like `0...010...0`, where the single 1 is in the i-th position counting from the right (rightmost being position 0)
• `&` is the “bitwise and operator”, where `any_bit & 0` is zero and `any_bit & 1` is `any_bit`
• `val & (1 << i)` is `0...0(i-th bit of val)0...0` in binary, where the i-th bit of val is in the i-th position of the result
• `!!` is a double negation: it converts zero to zero and any non-zero value to one
• `!!(val & (1 << i))` is either 0 or 1, and is exactly the i-th bit of val
• let me summarize what I understand. Let assume `val = '10010111'`; `for i=2` `!!(val & (1 << i))` = `!!('10010111' & '00000100')` = `!!('00000100')` = `1` If i is = 3 `!!(val & (1 << i))` = `!!('10010111' & '00001000')` = `!!('00000000')` = `0` Jun 1 '15 at 10:43
• This is correct! Jun 1 '15 at 10:48
• And this means if I give 16bit or longer data to shiftOut, it will send least significant 8 bits and ignore the rest. Jun 1 '15 at 10:52
• `shiftOut()` takes `uint8_t` data. If you call it with a 16-bit argument, the compiler will implicitly remove the 8 most significant bits before the actual call to `shiftOut()`. Jun 1 '15 at 11:01
• @SteveMcDonald: Yes, the output would be the same without the double negation, because `digitalWrite()` interprets any non-zero value (not just 1) as meaning `HIGH`. Apparently, the author of `shiftOut()` did not want to rely on this behavior, and instead wanted to always call `digitalWrite()` with either 0 (i.e. `LOW`) or 1 (`HIGH`). Oct 1 '17 at 12:34