The line
temp = (scratchVal[0] & 0xff) | ((scratchVal[1] << 8) & 0xff00);
is creating an unsigned 16-bit integer value from two bytes originating in scratchVal
. A single &
in this context is not the address operator but bitwise AND. So the lower byte of temp
is set from the first byte contained in scratchVal
, and the upper byte of temp
is set by left-shifting the second byte contained in scratchVal
. The two resulting numbers are joined together using bitwise OR |
. To avoid sign extension or other unwanted bits the masks 0xff
and 0xff00
are used to ensure all undesirables are zero.
Presented visually, if scratchVal
contains the bits aaaaaaaa bbbbbbbb
in the first two bytes then temp will end up as an unsigned integer with the bit pattern bbbbbbbbaaaaaaaa
.
The second question asked why they're calling -getBytes:length:
. The line
[data getBytes:&scratchVal length:data.length];
reads the bytes from data
into the scratchVal
temporary buffer.
In response to the question in the comment
why it is needed to left shift the bits to concatenate them
A simple assignment won't work. Assuming again that scratchVal
is a char
buffer containing the bits aaaaaaaa bbbbbbbb
, the code
temp = scratchVal[0];
would make temp equal to the UInt16
equivalent of the bits aaaaaaaa
. You can't use addition because the result will be whatever value comes from adding the two bytes together (aaaaaaaa
+ bbbbbbbb
).
Using real numbers as an example, suppose the first two bytes of scratchVal
are equal to 0x7f 0x7f
.
temp = scratchVal[0] + scratchVal[1];
Turns out to be 0x7f + 0x7f
= 0xfe
which is not the purpose of this code.
Building the value using OR can be better understood by breaking it down into steps.
The first part of the expression is scratchVal[0] & 0xff
= 0x7f & 0xff
= 0x7f
The second part is (scratchVal[1] << 8) & 0xff00
= (0x7f << 8) & 0xff
= 0x7f00 & 0xff
= 0x7f00
The final result in this case is 0x7f | 0x7f00
= 0x7f7f
.