Tricky interview question for mid-level C++ developer
Let's get this one step at a time:
((char*)&n)
This casts the address of the variable n
from unsigned long long*
to char*
. This is legal and actually accessing objects of different types via pointer of char is one of the very few "type punning" cases accepted by the language. This in effect allows you to access the memory of the object n
as an array of bytes (aka char
in C++)
((char*)&n)[sizeof(unsigned long long)-1]
You access the last byte of the object n
. Remember sizeof
returns the dimension of a data type in bytes (in C++ char
has an alter ego of byte)
((char*)&n)[sizeof(unsigned long long)-1] = 0xFF;
You set the last byte of n
to the value 0xFF
.
Since n
was 0
initially the layout memory of n
is now:
00 .. 00 FF
Now notice the ...
I put in the middle. That's not because I am lazy to copy paste the values the amount of bytes n
has, it's because the size of unsigned long long
is not set by the standard to a fixed dimension. There are some restrictions, but it can vary from implementation to implementation. So this is the first "unknown". However on most modern architectures sizeof (unsigned long long)
is 8, so we are going to go with this, but in a serious interview you are expected to mention this.
The other "unknown" is how these bytes are interpreted. Unsigned integers are simply encoded in binary. But it can be little endian or big endian. x86 is little endian so we are going with it for the exemplification. And again, in a serious interview you are expected to mention this.
n >>= 7*8;
This right shifts the value of n
56 times. Pay attention, now we are talking about the value of n
, not the bytes in memory. With our assumptions (size 8, little endian) the value encoded in memory is 0xFF000000 00000000
so shifting it 7*8
times will result in the value 0xFF
which is 255
.
So, assuming sizeof(unsigned long long)
is 8
and a little endian encoding the program prints 255
to the console.
If we are talking about a big endian system, the memory layout after setting the last byte to 0xff
is still the same: 00 ... 00 FF
, but now the value encoded is 0xFF
. So the result of n >>= 7*8;
would be 0
. In a big endian system the program would print 0
to the console.
As pointed out in the comments, there are other assumptions:
char
being 8 bits. Althoughsizeof(char)
is guaranteed to be1
, it doesn't have to have 8 bits. All modern systems I know of have bits grouped in 8-bit bytes.integers don't have to be little or big endian. There can be other arrangement patterns like middle endian. Being something other than little or big endian is considered esoteric nowadays.
Cast the address of n
to a pointer to chars, set the 7th (assuming sizeof(long long)==8) char element to 0xff, then right-shift the result (as a long long) by 56 bits.