Help with syntax

I was looking over the Arduino core libary functions to learn how the shiftOut function works:

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);            
      }
}

The part I can’t quite come to terms with is the !! used in the:

digitalWrite(dataPin, !!(val & (1 << i)));
and
digitalWrite(dataPin, !!(val & (1 << (7 - i))));

I found nothing in the extended reference to explain !! usage (why two of them in a row?) in these example.

I think I understand useage of a single !, to invert the results, but two in a row? Even a quick search on google failed to give me a hint.

Anyone care to educate me?

Thanks;

Lefty

!! isn't one operator, but 2.

!5 = 0 !0 = 1

!!5 = 1 !!0 = 0

It ensures the result is either 0 or 1.

Yep. That just hit me too. That’s a good one for my bag of tricks.

in the expression !!(val & (1 << i))

assume val is 0x06 - 00000110 and i is 1
then val & (1<<i) is 00000010

!(val & (1<<i)) is 0
!!(val &(1<<i)) is 1

The trick relies on the fact that the C++ standard requires the result of boolean expressions to be zero (false is required to be 0) or one (true is required to be 1).

I believe with the C standards, boolean results are determined by the compiler vendor. Microsoft might use zero and -1. Borland might use 0 and 0xFF. GNU might use zero and one.

OK. I thought the C standard was a 0 was a false result and any other value was a true result, but maybe that is wrong and only 0 and 1 values can be converted to a boolean logic result?. Not sure about C++.

In rFree’s posting above it shows:

!5 = 0, doesn’t that imply that any value other then 0 is considered a 1?

Lefty

OK. I thought the C standard was a 0 was a false result and any other value was a true result, but maybe that is wrong and only 0 and 1 values can be converted to a boolean logic result?

Your thoughts are correct for the value going into the expression.

Think of a boolean expression like a function call. You can pass in nearly anything (0, 1, 5, 3.1415). Any non-zero value going in is treated as true. Zero going in is treated as false. This part works the same in C and C++.

In C++, what comes out is always a 0 or 1. In C, what comes out is compiler dependent.

In rFree's posting above it shows: !5 = 0, doesn't that imply that any value other then 0 is considered a 1?

In C++, this essentially becomes...

  ! (5 != 0)
  ! (true)
  false  /* which is defined to always be 0 */

Adding the next logical-not...

  ! ! (5 != 0)
  ! ! (true)
  ! false
  true  /* which is defined to always be 1 */

In C, the first result is essentially the same...

  ! (5 != 0)
  ! (non- zero)
  0

But the second result could be anything except zero...

  ! ! (5 != 0)
  ! ! (non-zero)
  ! (zero)
  (non-zero)

I'm having a difficult time describing this. Have I confused you even more?

No, I've following most of what people are responding with. However I'm still not clear on why the need for !! in my original posting. Why the need to force a non-zero result to one, using the !!, if any non-zero value would already be evaluated as true? The result is just passed to digitalWrite as a byte size variable where it is tested in a if statement as (value == 0), so again I'm not sure why the need to force the value to a 1 if it's non-zero already.

Does my question (or confusion) make sense?

Lefty

I believe with the C standards, boolean results are determined by the compiler vendor. Microsoft might use zero and -1. Borland might use 0 and 0xFF. GNU might use zero and one.

Well, if that’s the case they’re all wrong but GNU :slight_smile:

http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf

6.5.3.3
5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value compares equal to 0…

6.5.8
6 Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false

7.16 Boolean type and values <stdbool.h>
3 …They are true which expands to the integer constant 1, false which expands to the integer constant 0

I'm still not clear on why the need for !! in my original posting.

It's not needed. DigitalWrite() does it's own internal boolean conversion; only a zero argument will cause a zero to be written to the pin...

(However, it's not DOCUMENTED that way. It's also not documented to accept a boolean as the second argument. It's documented to accept values LOW and HIGH.)

It's not needed.

Thanks, that clears it up a bit.

Lefty

Thanks, that clears it up a bit.

Are you sure you didn’t mean that it doesn’t not clear it up a bit?

:smiley:

Anyway, interesting to know.
(sorry for being sligthly off-topic)

Well, if that’s the case they’re all wrong but GNU

It’s been … well … a few years since I needed to know about that stuff. I guess I should refresh my brain before opening my big mouth.