Динамический сдвиг влево ИЛИ вправо

#c

#c

Вопрос:

У меня довольно простой вопрос. Есть ли способ динамического побитового сдвига влево ИЛИ вправо, например, в зависимости от знака int .

 signed int n = 3;
signed int m = -2;

int number1 = 8;
int number2 = 8;

//number1 shift n;
//number2 shift m;
  

В этом случае я хочу сдвинуть number1 на 3 бита влево и number2 на 2 бита вправо. Есть ли способ без if else этого?

Комментарии:

1. Вы должны сдвигать только целые числа без знака.

Ответ №1:

Для 32-разрядных:

x = (((длинный длинный)x) << 32) >> (32 — n)

Комментарии:

1. Мне нравится элегантность этого подхода, но это также должно работать для 64-битных целых чисел и может привести ко многим переполнениям.

2. Для 64-разрядной версии: (__int128)x << 64 >> (64 - n) . Работает только с компиляторами с поддержкой __int128 (gcc, clang). Вы можете динамически определять длину в битах с помощью CHAR_BIT*sizeof x , но гораздо сложнее получить тип для динамического приведения

Ответ №2:

 #include <stdio.h>

typedef unsigned (*fx_t)(unsigned, int);

unsigned shiftleft(unsigned val, int bits) {
  return val << bits;
}

unsigned shiftright(unsigned val, int bits) {
  return val >> (-bits);
}

unsigned shift(unsigned val, int bits) {
  static fx_t sshift[2] = {shiftright, shiftleft};
  return sshift[bits >= 0](val, bits);
}

int main(void) {
  signed int n = 3;
  signed int m = -2;
  unsigned number1 = 8;
  unsigned number2 = 8;

  printf("%un", shift(number1, n));
  printf("%un", shift(number2, m));

  return 0;
}
  

Вы можете «увидеть, как выполняется код» в ideone: http://ideone.com/F2vAB http://ideone.com/x1RbQ

Комментарии:

1. shiftright И shiftleft должно быть определено с static помощью, но я не хочу редактировать ответ и выводить его из синхронизации с ideone.

2. Это все еще использует условный ( bits >= 0 ) , так что там скрыто if .

3. вы можете использовать -(bits >> (CHAR_BIT*sizeof bits - 1)) или (unsigned)bits >> (CHAR_BIT*sizeof bits - 1)) удалить, если

Ответ №3:

?: Считается ли как if-else ?

 int x = (n > 0) ? (number1 << n) : (number1 >> (-n));
int y = (m > 0) ? (number2 << n) : (number2 >> (-m));
  

Комментарии:

1. ‘?:’ считается как ‘if-else’, но я нахожу этот ответ удовлетворяющим моим потребностям, поскольку он короткий и надежный. Это не означает, что другие ответы неверны. Спасибо всем.

Ответ №4:

Нет, вам понадобится условие.

Операторы побитового сдвига имеют неопределенное поведение, если вы используете отрицательное значение справа от них.

Ответ №5:

Если значение числа сдвигаемых битов отрицательное, результат не определен. Однако вы можете поэкспериментировать со своим компилятором, может случиться так, что ваш компилятор сместится в противоположном направлении. И, конечно, вы могли бы использовать ?: , но это просто другой способ выражения if-else.