shiftOut what happens with the variables?

I was looking in to the function shiftOut (below) to try and understand how the arduino board communicate with the shift register and it got me thinking about how all these bits are perceived by the program.

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

As far as I can understand so far, all data manipulation made by the Arduino treats the data in a bitwise maner. Assuming that i understood it right, an operation like !!(val &(1<<5)) where val == 1001 1101 would be done as:

!!(1001 1101 &(0000 0001<<5))
!!(1001 1101 &(0001 0000))
!!(0001 0000) == 0000 0001

At this point I don't know if I understood the double negation right. Because if it was made bitwise, it should return 0001 0000 (or am I wrong?). But, as this operation is used to assign the value of the dataPin with digitalWrite I assumed that the end value should be 1 or 0. Is that it?
Another thing that confuses me is that the digitalWrite function is expecting a value "HIGH" or "LOW". And loking through the forum i read people saying that it is not a good idea to feed digitalWrite with a boolean variable. But isn't it what this function does?

The last thing that confuses me is the bitOrder variable. It i defined as unit8_t and it is compared whit a string of char (LSBFIRST). How would this string be read as unit8_t? Would each char be perceived as a 8 bit vector?

I much prefer using SPI.transfer() to send data to a shift register.
The SPI hardware is a dedicated register, you load a byte into into and the hardware blasts it out indepedently of the sofware.

Example:

digitalWrite (ssPin, LOW); // typically 10 on an Uno, connect to shift register output latch signal
SPI.transfer (yourByteOfData); // shift register CLK to Uno pin 13 (SCK), Data to Uno pin 11 (MOSI)
digitalWrite (ssPin, HIGH); // shift register output updates on this rising edge

Isn't that way cleaner than the shiftOut() mess?
Default settings used when SPI.begin() is called in void setup() are MSBFIRST and clock speed of 4 MHz. Can be increased to 8 MHz max on an Uno, or slowed to 2 MHz, 1 MHz, 500 KHz, 250 KHz, 125 KHz, and 62.5 KHz I think.
Shift register like 74HC595 and TPIC6B595 will work at 8 MHz just fine. I've daisy chained 45 of them at that speed.

heitorwwa:
As far as I can understand so far, all data manipulation made by the Arduino treats the data in a bitwise maner. Assuming that i understood it right, an operation like !!(val &(1<<5)) where val == 1001 1101 would be done as:

!!(1001 1101 &(0000 0001<<5))
!!(1001 1101 &(0001 0000))
!!(0001 0000) == 0000 0001

At this point I don't know if I understood the double negation right. Because if it was made bitwise, it should return 0001 0000 (or am I wrong?). But, as this operation is used to assign the value of the dataPin with
digitalWrite I assumed that the end value should be 1 or 0. Is that it?

The double negation does indeed turn any non-zero number into 1 and leaves the value 0 as 0

Another thing that confuses me is that the digitalWrite function is expecting a value "HIGH" or "LOW". And loking through the forum i read people saying that it is not a good idea to feed digitalWrite with a boolean variable. But isn't it what this function does?

Technically speaking, yes, digitalWrite takes HIGH or LOW but if you look at their definition, you will see that HIGH is 1 and LOW is 0. Theoretically speaking, the arduino IDE could, in the future, change these definitions and if you only ever use HIGH and LOW, your code would continue to work. On the practical side, the possibility of these ever changing is pretty much zero since it would break so much code.

The last thing that confuses me is the bitOrder variable. It i defined as unit8_t and it is compared whit a string of char (LSBFIRST). How would this string be read as unit8_t? Would each char be perceived as a 8 bit vector?

No, it is not compared to a string. LSBFIRST is just a defined constant like HIGH or LOW. It makes it much easier to read by humans

#define LSBFIRST 1
#define MSBFIRST 0
#define dataPin 4
#define clockPin 5

shiftOut(dataPin, clockPin, LSBFIRST, 0x55);

vs.

#define dataPin 4
#define clockPin 5

shiftOut(dataPin, clockPin, 1, 0x55);  // have to remember that '1' means LSBFIRST

heitorwwa:
Assuming that i understood it right, an operation like !!(val &(1<<5)) where val == 1001 1101 would be done as:
!!(1001 1101 &(0000 0001<<5))
!!(1001 1101 &(0001 0000))
!!(0001 0000) == 0000 0001

You shifted 4 instead of 5:
!!(val &(1<<5)) where val == 10011101
!!(10011101 & (1<<5))
!!(10011101 & 00100000)

!!(00000000)

!true

false
So we now know that Bit 5 of 'val' is 'false'/0/LOW
If you want Bit 4:
!!(val &(1<<4)) where val == 10011101
!!(10011101 & (1<<4))
!!(10011101 & 00010000)

!!(00010000)

!false

true

Only the most anal programmers will use 'digitalWrite(pin, x ? HIGH : LOW);' to make sure that their code will work in some far future time when HIGH is not 1 or LOW is not 0. (or maybe 1 is not 'true' or 'false' is not 0).