# Bytes from integer using bitwise operators

So I am extremely confused with using bitwise shifts used to extract the bytes from an integer. I find that if I do something like this...

int i = 512;
i & 0xFF; // this gives me the first byte


That must mean i & 0xFF gives me the first byte that is stored in memory. In other words, i & 0xFF is the first of the four bytes i consists of stored at the lowest memory address. Next, I think that i << 8 & 0xFF will then shift everything left by 8 bits and giving me the second byte. However, it is actually the opposite and only i >> 8 & 0xFF gives me the next byte. I do not understand why this is true. To me, it makes the most sense to left shift to get the next byte so why do I need to right shift by 8 to get the proceeding byte?

• i & 0xFF actually gives you the last byte, i.e. i % 256 – Jakube Jul 20 '18 at 8:56
• Okay so if i & 0xFF gives the last byte, then i >> 8 & 0xFF would give the second last byte? – Zachery Kish Jul 20 '18 at 9:02
• Yes, i >> 8 is basically a division by 256. – Jakube Jul 20 '18 at 9:16
• So how does this relate to how the bytes are actually stored in memory? For example, on my machine the bytes are ordered in little endian so that means that taking i & 0xFF is getting the byte at the last memory address since it is the last byte? – Zachery Kish Jul 20 '18 at 9:20
• It doesn't. All those operations are independent of endianness. E.g. if i = 0x12345678. Then i & 0xFF in big endian is [1, 2, 3, 4, 5, 6, 7, 8] & [0, 0, 0, 0, 0, 0, F, F] = [0, 0, 0, 0, 0, 0, 7, 8] = 0x78, and in little endian is [8, 7, 6, 5, 4, 3, 2, 1] & [F, F, 0, 0, 0, 0, 0, 0] = [8, 7, 0, 0, 0, 0, 0, 0] = 0x78]. And the same with the shift operations. I even checked the C++ standard. It defines i >> x as i / 2^x. – Jakube Jul 20 '18 at 9:42

Contrary to what you think, extracing bytes by shifting and masking is completely unrelated to the storage order (both little-endian and big-endian storage schemes exist and don't influence the results).

An int variable is represented by 32 bits. The least significant byte is made of the eight least significant bits and you obtain them by

i & 0xFF
0b 111111111 0101010 01010101 000000000 => 0b 00000000 00000000 00000000 00000000


The neighboring byte is made of the eight neighboring bits; you discard the eight least significant bits by shifting (>>), then mask out:

(i >> 8) & 0xFF
0b 11111111 10101010 01010101 000000000 => 0b 00000000 00000000 00000000 01010101


And similarly for the remaining two bytes, with shifts of 16 and 24 (most significant byte).

Notice that I cared not to use the terms left/right and first/last, which are meaningless as they refer to some graphical representation or memory storage order. In the examples, the numbers are understood as binary numbers written with lsb on the right (and spacers for clarity), which is the most common convention.

• I realise the point you're trying to make but I feel this would be clearer if you did use terms such as "left" and "right" but pointed out that their meaning is in terms of the ordinary way of writing binary numbers and has nothing to do with how they're actually laid out in some computer's memory. – David Richerby Jul 20 '18 at 15:21
• @DavidRicherby: the terms least/most significant are more relevant. – Yves Daoust Jul 20 '18 at 15:45
• This makes sense. Also, when I assign these numbers to say a bitset or something, will all those leading 0s be ignored and only the first 8 bits be kept? – Zachery Kish Jul 20 '18 at 17:45
• @ZacheryKish: I represented what happens in the registers. What it becomes next depends on casts. – Yves Daoust Jul 20 '18 at 19:21