Макро значения, определенные с помощью битовых сдвигов - PullRequest
0 голосов
/ 24 мая 2018

Я просматривал старый исходный проект, пытаясь заставить его скомпилироваться и запустить (это старая игра, которая была загружена на GitHub).Я думаю, что большая часть кода была написана с учетом C-style / C-синтаксиса (много typedef struct {...} и т.п.), и я заметил, что они определяют определенные макросы с помощью следующего стиля:

#define MyMacroOne (1<<0) //This equals 1
#define MyMacroTwo (1<<1) //This equals 2, etc.

Итак, мой вопрос сейчас такой: есть ли причина, по которой макросы будут определены таким образом?Потому что, например, 0x01 и 0x02 являются числовым результатом выше.Или система будет читать не MyMacroOne = 0x01, а скорее как «объект сдвига» со значением (1 << 0)?</p>


РЕДАКТИРОВАТЬ: Спасибо за все ваши вклады!

Ответы [ 4 ]

0 голосов
/ 24 мая 2018

Вы всегда можете использовать постоянные целочисленные сдвиги выражений в качестве способа выражения (кратных) степеней двух, т. Е. Multiple*(2 to the N-th power) = Mutliple << N (с некоторыми оговорками, связанными с достижением гарантированных пределов размера целочисленных типов и наборов UB в *) и в значительной степени полагаются на то, что компилятор их свернет.

Целочисленное выражение, состоящее из целочисленных констант, определяется как целочисленное константное выражение .Их можно использовать для указания размеров массива, меток падежей и тому подобного, поэтому каждый компилятор должен иметь возможность сворачивать их в одно промежуточное звено, и было бы глупо не использовать эту возможность даже там, где это строго не требуется.


* Например: вы можете сделать 1U<<15, но в 16 вы должны переключиться по крайней мере на 1L<<16, потому что ints / unsigneds требуется только для того, чтобы иметь как минимум 16 бит и левостороннее смещениецелое число по ширине или в месте, где находится его знаковый бит, не определено (6.5.7p4) :

Результатом E1 << E2 является E1 со смещением влево E2битовые позиции;освобожденные биты заполнены нулями.Если E1 имеет тип без знака, значение результата будет E1 x 2E2, уменьшенное по модулю на единицу больше, чем максимальное значение, представляемое в типе результата.Если E1 имеет тип со знаком и неотрицательное значение, а E1 x 2E2 представимо в типе результата, то это итоговое значение;в противном случае поведение не определено. </p>

0 голосов
/ 24 мая 2018

Это удобно для людей

, например

#define PIN0 (1u<<0)
#define PIN5 (1u<<5)

#define PIN0MASK (~(1u<<0))
#define PIN5MASK (~(1u<<5))

, и также легко увидеть, есть ли правильная битовая позиция.он не делает код медленнее, так как он рассчитывается во время компиляции

0 голосов
/ 24 мая 2018

Это делает его более интуитивным и менее подверженным ошибкам при определении битовых значений, особенно в многобитовых битовых полях.Например, сравните

#define POWER_ON     (1u << 0)
#define LIGHT_ON     (1u << 1)
#define MOTOR_ON     (1u << 2)
#define SPEED_STOP   (0u << 3)
#define SPEED_SLOW   (1u << 3)
#define SPEED_FAST   (2u << 3)
#define SPEED_FULL   (3u << 3)
#define LOCK_ON      (1u << 5)

и

#define POWER_ON     0x01
#define LIGHT_ON     0x02
#define MOTOR_ON     0x04
#define SPEED_STOP   0x00
#define SPEED_SLOW   0x08
#define SPEED_FAST   0x10
#define SPEED_FULL   0x18
#define LOCK_ON      0x20
0 голосов
/ 24 мая 2018

Макрос - это просто текст замены.Везде макрос заменен текстом замены !!Это удобно, особенно если вы хотите назвать что-то постоянное, что в противном случае может привести к ошибкам.

...