Ответ 1
Позвольте получить это один шаг за раз:
((char*)&n)
Это приводит к преобразованию адреса переменной n
из unsigned long long*
в char*
. Это допустимо, и на самом деле доступ к объектам разных типов через указатель char является одним из очень немногих случаев "наказания за тип", принятых языком. По сути, это позволяет вам получить доступ к памяти объекта n
в виде массива байтов (он же char
в C++)
((char*)&n)[sizeof(unsigned long long)-1]
Вы получаете доступ к последнему байту объекта n
. Помните, sizeof
возвращает размерность типа данных в байтах (в C++ char
имеет альтер-эго байта)
((char*)&n)[sizeof(unsigned long long)-1] = 0xFF;
Вы устанавливаете последний байт n
в значение 0xFF
.
Поскольку n
было 0
изначально, память макета n
теперь:
00 .. 00 FF
Теперь обратите внимание на ...
Я положил в середине. Это не потому, что мне лень копировать и вставлять значения, которые имеет количество байтов n
, а потому, что размер unsigned long long
не установлен стандартом в фиксированное измерение. Существуют некоторые ограничения, но они могут варьироваться от реализации к реализации. Так что это первое "неизвестное". Однако на большинстве современных архитектур sizeof (unsigned long long)
равен 8, поэтому мы собираемся пойти на это, но в серьезном интервью вы должны упомянуть об этом.
Другое "неизвестное" - как эти байты интерпретируются. Целые числа без знака просто кодируются в двоичном виде. Но это может быть порядок с прямым или обратным порядком. x86 является прямым порядком байтов, поэтому мы приведем его в качестве примера. И снова, в серьезном интервью вы должны упомянуть об этом.
n >>= 7*8;
Это право сдвигает значение n
56 раз. Обратите внимание, сейчас речь идет о значении n
, а не байтов в памяти. С нашими предположениями (размер 8, младший порядок) значение, закодированное в памяти, равно 0xFF000000 00000000
поэтому смещение его 7*8
раз приведет к значению 0xFF
которое равно 255
.
Итак, если предположить, что sizeof(unsigned long long)
равен 8
а кодирование с прямым порядком байтов немного печатает, программа выводит 255
на консоль.
Если мы говорим о системе с 0xff
байтов, структура памяти после установки последнего байта 0xff
остается прежней: 00... 00 FF
, но теперь закодированное значение равно 0xFF
. Так что результат n >>= 7*8;
будет 0
. В системе с прямым порядком байтов программа выводит 0
на консоль.
Как указано в комментариях, есть и другие предположения:
-
char
8 бит. Хотяsizeof(char)
гарантированно равен1
, он не должен иметь 8 бит. Все известные мне современные системы имеют биты, сгруппированные в 8-битные байты. -
целые числа не должны быть маленькими или старшими. Могут быть другие схемы расположения, например, со средним порядком байтов. Быть чем-то иным, чем маленький или большой порядок байтов считается сегодня эзотерическим.