Как избежать интегрального продвижения для побитовых операций
Я поражен, что VisualStudio 2015 настаивает на продвижении WORD
(unsigned short
) для unsigned int
когда только WORD
значения участвуют только в битовых манипуляциях. (т. е. повышает 16 бит до 32 бит при выполнении 16 бит | 16 бит).
например
// where WORD is a 'unsigned short'
const WORD kFlag = 1;
WORD old = 2;
auto value = old | kFlag; // why the blazes is value an unsigned int (32 bits)
Кроме того, есть ли способ получить 0x86 встроенных функций для WORD|WORD
? Я, конечно, не хочу платить (16->32|16->)->16. И при этом этот код не должен использовать больше чем пара 16-битных регистров, а не несколько 32-битных регистров.
Но использование реестра на самом деле просто в стороне. Оптимизатор может делать все, что пожелает, если результаты для меня неразличимы. (т.е. он не должен изменять размер видимым образом).
Основная проблема для меня заключается в том, что использование флагов |kFlagValue приводит к более широкой сущности, а затем добавление этого в шаблон приводит к ошибке несоответствия типов (шаблон гораздо длиннее, чем я хотел бы получить, но дело в том, что это занимает два аргумента, и они должны совпадать по типу или быть тривиально конвертируемыми, но это не так из-за этого автоматического правила увеличения размера).
Если бы у меня был доступ к "консервативному набору функций обработки битов", я мог бы использовать:
flag non-promoting-bit-operator kFlagValue
Для достижения моих целей.
Я думаю, мне нужно написать это или использовать повсеместное приведение типов из-за этого печального правила.
C++ не должен продвигать в этом случае. Это был плохой выбор языка.
1 ответ
Почему value
повышен до более крупного типа? Потому что спецификация языка говорит, что это (16-битный unsigned short
будет преобразован в 32-разрядный int
). 16-битные операции на x86 фактически влекут за собой штраф по сравнению с соответствующими 32-битными (из-за префикса кода операции), поэтому 32-битная версия может работать быстрее.