Переключение заданного диапазона битов unsigned int в C
Я пытаюсь заменить следующий фрагмент кода
// code version 1
unsigned int time_stx = 11; // given range start
unsigned int time_enx = 19; // given range end
unsigned int time = 0; // desired output
while(time_stx < time_enx) time |= (1 << time_stx++);
Со следующим без петли
// code version 2
unsigned int time_stx = 11;
unsigned int time_enx = 19;
unsigned int time = (1 << time_enx) - (1 << time_stx);
Получается, что в коде версии 1, time = 522240;
в коде версии 2, time = 0;
Когда я использую
printf("%un", time);
Чтобы сравнить результат. Я хотел бы знать, почему это происходит и есть ли более быстрый способ переключения битов в заданном диапазоне. Мой компилятор-gcc (Debian 4.9.2-10) 4.9.2.
Правка:
Спасибо за ответы. Я совершил глупую ошибку, и я ... чувствую себя неловко, отправляя свой вопрос без дальнейшего изучения моих кодов. Я сделал
unsigned int time_stx = 11;
unsigned int time_enx = 19;
unsigned int time1 = 0;
while(time_stx < time_enx) time1 |= (1 << time_stx++); // version 1
//// what I should, but forgotten to do
// time_stx = 11;
// time_enx = 19;
// where time_stx = time_enx now...
unsigned int time2 = (1 << time_enx) - (1 << time_stx); // version 2
// then obviously
printf("time1 = %un", time1); // time1 = 522240
printf("time2 = %un", time2); // time2 = 0
Я приношу свои извинения за причиненные неудобства.
Замечание: и time_stx
, и time_enx
генерируются во время выполнения и не являются фиксированными.
Как предположили, что я допустил ошибку, и теперь проблема решена. Спасибо!!
1 ответ:
Читать битные твид-хаки. Даже если ответа там нет, вы будете лучше образованы в битвах. Кроме того, исходный код просто устанавливает биты в диапазоне; переключение означает превращение 1 бита в 0 бит и наоборот (обычно достигается с помощью
^
или xor).Что касается кода, то я преобразовал три варианта выражения в следующий код C:
#include <stdio.h> static void print(unsigned int v) { printf("0x%.8X = %u\n", v, v); } static void bit_setter1(void) { unsigned int time_stx = 11; // given range start unsigned int time_enx = 19; // given range end unsigned int time = 0; // desired output while (time_stx < time_enx) time |= (1 << time_stx++); print(time); } static void bit_setter2(void) { unsigned int time_stx = 11; unsigned int time_enx = 19; unsigned int time = (1 << time_enx) - (1 << time_stx); print(time); } static void bit_setter3(void) { unsigned int time = 0xFF << 11; print(time); } int main(void) { bit_setter1(); bit_setter2(); bit_setter3(); return 0; }
Когда я смотрю на ассемблер для него (GCC 5.1.0 на Mac OS X 10.10.3), я получить:
Это удивительно большая коллекция этикеток! Компилятор полностью оценил все три минимальные функции.globl _main _main: LFB5: LM1: LVL0: subq $8, %rsp LCFI0: LBB28: LBB29: LBB30: LBB31: LM2: movl $522240, %edx movl $522240, %esi leaq LC0(%rip), %rdi xorl %eax, %eax call _printf LVL1: LBE31: LBE30: LBE29: LBE28: LBB32: LBB33: LBB34: LBB35: movl $522240, %edx movl $522240, %esi xorl %eax, %eax leaq LC0(%rip), %rdi call _printf LVL2: LBE35: LBE34: LBE33: LBE32: LBB36: LBB37: LBB38: LBB39: movl $522240, %edx movl $522240, %esi xorl %eax, %eax leaq LC0(%rip), %rdi call _printf LVL3: LBE39: LBE38: LBE37: LBE36: LM3: xorl %eax, %eax addq $8, %rsp LCFI1: ret
bit_setterN()
и встроил их вместе с вызовомmain()
. Это включает в себя оценку выражений до 522240 каждый раз. Компиляторы хороши в оптимизации. Напишите четкий код и дайте им это сделать, и они оптимизируют лучше, чем вы. Ясно, что если 11 и 19 не зафиксированы в вашем коде (они своего рода вычисляемые переменные, которые могут изменяться во время выполнения), то предварительное вычисление не так просто (иbit_setter3()
не является стартером). Тогда код без цикла будет работать нормально, как и код цикла.Для записи вывод будет следующим:
0x0007F800 = 522240 0x0007F800 = 522240 0x0007F800 = 522240
Если ваш компилятор Debian дает вам ноль от одного из фрагментов кода, то есть либо разница между тем, что вы скомпилировали, и тем, что вы опубликовали, либо ошибка в компиляторе. В целом, и никакого неуважения не предполагается, более вероятно, что вы допустили ошибку, чем то, что компилятор имеет ошибку в нем, которая появляется в коде так просто, как это.