Двоичные константы, такие как 0b1111111
, не определены стандартом C и были введены как расширение некоторыми реализациями C несколько позже, поэтому в более раннем коде обязательно использовались восьмеричные и шестнадцатеричные константы, и программисты привыкли к ним , Кроме того, восьмеричное число более компактно, и я могу посчитать количество установленных бит в 0177
легче, чем в 0b1111111
. Человек быстро привыкнет к тому, что 7
означает три набора битов.
В (*(int *)&(w))
, &(w)
принимает адрес объекта, обозначенный w
. Затем (int *)
преобразует этот адрес из типа «указатель на тип w» в «указатель на int». Затем *
разыменовывает этот указатель, номинально создавая значение int
.
Цель состоит в том, чтобы получить доступ к первым байтам w
, как если бы они были int
, эффективно получая необработанные биты, которые являются в w
вместо того, чтобы интерпретировать его как структуру или любой другой тип. Это называется псевдоним .
Псевдоним таким образом не поддерживается стандартом C, но многие реализации C позволяют это делать, и показанный вами код кажется написанным специально для такой реализации.
Поддерживаемый способ получения необработанных битов объекта - это индивидуальное копирование байтов, например:
int b;
memcpy(&b, &w, sizeof b);
Хотя это выглядит как вызов функции, хорошо компиляторы распознают его как запрос доступа к первым байтам w
, как если бы они были int
, и оптимизируют его. Результатом может быть одна инструкция загрузки. Однако, оборачивая это в макрос, который выдает int
как значение, возникают некоторые сложности, которые я оставлю для дальнейшего обсуждения в другом месте. (Вы можете задать новый вопрос об этом, если хотите.)