Я читал, что C удерживает выполнение из сдвигов, и его можно найти в конкретном процессоре .h.Сохраняет ли C перенос о бит с << or a >> бит сдвиг?
Это правда, и я должен использовать его? или должен сам выработать бит?
Я читал, что C удерживает выполнение из сдвигов, и его можно найти в конкретном процессоре .h.Сохраняет ли C перенос о бит с << or a >> бит сдвиг?
Это правда, и я должен использовать его? или должен сам выработать бит?
Там нет стандартного способа получить доступ к бит переноса (ы) примитивных операций в С.
Вы либо должны выполнить сдвиг в большом типе данных:
uint16_t foo = ...;
uint32_t tmp = (uint32_t)foo << shift;
uint16_t result = (uint16_t)tmp;
uint16_t carry = (uint16_t)(tmp >> 16);
или по выполняя обратный сдвиг:
uint16_t result = foo << shift;
uint16_t carry = foo >> (16 - shift);
Обратите внимание, что этот второй метод вызывает неопределенное поведение, если shift == 0
, так что вам нужно обрабатывать этот случай отдельно.
Да, переход к большему типу данных является лучшим, когда он доступен. Примечание. Ответы также вызывают неопределенное поведение, если «shift <= 0» или «shift> = 16». Обработка этих случаев, однако, не должна быть большой проблемой, хотя для тех, кто использует ваш прекрасный ответ. – chux
@chux: Спасибо! Однако 'shift' < 0 or > = 16 - это UB, но вы это делаете, тогда как мой второй метод также означает, что' shift == 0' также является UB. –
В обзоре, я думаю, что сдвиг '0' может быть в порядке во втором методе. Конечно, мы оба думаем: 'uint16_t result = foo << 0' ОК? Но не определяется ли 'uint16_t carry = foo >> 16'? – chux
Стандарт C делает не обеспечивает доступ к выполнению из смен.
Некоторые, не все, реализации C имеют файлы, специфичные для процессора. H или другие расширения, которые разрешают доступ.
В любом случае вам следует избегать использования функциональных возможностей от файлов-спецификаторов процессора или расширений. Но если необходимо использовать, рассмотрите также, написание решения C Standard, по крайней мере, как часть документации. см. Рекомендуемое решение @Oli Charlesworth.
В целом, для создания эффективного портативного кода может потребоваться рассмотреть проблему на более высоком уровне и не использовать переносные выходы. С другой стороны, если это для узкого круга машин, пойдите с тем, что работает для вас (или тех, кто платит вашу зарплату).
В моих предыдущих опубликованных примерах указывались различные недостатки. Я вижу их сейчас как зависимые от реализации. Удалены.
Вы правы, чтобы сказать, что это границы для переносимости. Отрицательные отрицательные значения слева - это неопределенное поведение, которое ничего, кроме * портативного *. Отрицательные значения с правосторонним сдвигом - это поведение, определяемое реализацией, которое может включать сохранение знака, если не сейчас, то в какой-то момент в будущем. Оба следует избегать. – Sebivor
@ неопределенное поведение Согласовано с оценкой моих «пограничных» примеров и удалило их. – chux
Возможно, для этого используется встроенный встроенный asm. –
Мне любопытно, как использовать ваш случай для проверки выполнения. Когда это делается на уровне сборки, это обычно метод проверки значения бит в регистре в последовательности. В C есть другие способы сделать это, не требуя проверки выполнения. Если для него существует конкретная для процессора реализация, вы не получите большой производительности, если вам не нужны настройки производительности, которые регистрируются в микросекундах за итерацию. – lurker