C - Повернуть 64-битное целое число без знака

сегодня я пытался написать функцию, которая должна вращать данное 64-битное целое число на n бит вправо, но также и влево, если n отрицательно. Конечно, биты из целого числа должны быть заменены на другой стороне.

Я сохранил функцию довольно простой.

void rotate(uint64_t *i, int n) 
  uint64_t one = 1;
  if(n > 0) {
      do {
           int storeBit = *i & one;
           *i = *i >> 1;
           if(storeBit == 1)
              *i |= 0x80000000000000;
           n--;
          }while(n>0);
   }
 }

возможные входы:

uint64_t num = 0x2;
rotate(&num, 1); // num should be 0x1
rotate(&num, -1); // num should be 0x2, again
rotate(&num, 62); // num should 0x8

К сожалению, я не мог понять это. Я надеялся, что кто-нибудь сможет мне помочь.

РЕДАКТИРОВАТЬ: Теперь код онлайн. Сорри, это заняло некоторое время. У меня были некоторые трудности с редактором. Но я просто сделал это для вращения вправо. Поворот влево отсутствует, потому что я его не делал.


person Community    schedule 07.11.2013    source источник
comment
Есть ли какой-нибудь код внутри функции rotate() где-то еще? Объявление функции на самом деле не означает, что что-то произойдет, если оно где-то не реализовано.   -  person jonhopkins    schedule 07.11.2013
comment
@glglgl: Ну, я считал 64-битное целое число одним числом. Итак, я переместил его один за другим, например. вправо, пока n не уменьшится до нуля. Каждый раз я сохранял значение бита, который был повернут, и я повернул этот бит с другой стороны.   -  person    schedule 07.11.2013
comment
@user2965601 user2965601, это похоже на то, что вы должны делать. Можете ли вы отредактировать свой вопрос, чтобы показать, что у вас есть на данный момент, и как выглядит неправильный вывод?   -  person jonhopkins    schedule 07.11.2013
comment
@jonhopkins: Нет, код должен вращаться, а затем я вызываю его в основной функции.   -  person    schedule 07.11.2013
comment
@user2965601 user2965601 нам действительно нужно увидеть код в rotate, чтобы помочь, и указание на то, какие части неясны, также поможет. Предпочтительно SSCCE, то есть с заголовками, main и т. д.   -  person Shafik Yaghmour    schedule 07.11.2013
comment
@user2965601 user2965601 Чтобы помочь вам узнать, что вы не смогли сделать, нам нужен ваш код. Ваш код rotate(). Тот, который не работает.   -  person glglgl    schedule 07.11.2013
comment
@ user2965601, где-то еще, я просто имел в виду тот факт, что вы показали нам только объявление функции, то есть void rotate(uint64_t *i, int n);. Итак, я предполагал, что у вас есть фактическая реализация, void rotate(uint64_t *i, int n) { // your code } где-то еще в вашем файле.   -  person jonhopkins    schedule 07.11.2013
comment
Мы не можем помочь вам с кодом, который мы не видим. Пожалуйста, включите свою копию функции rotate.   -  person Raymond Chen    schedule 07.11.2013
comment
Код есть в сети. Извините, это заняло некоторое время, но у меня были некоторые трудности с редактором кода.   -  person    schedule 07.11.2013
comment
stackoverflow.com/questions/3323633/   -  person Exceptyon    schedule 07.11.2013
comment
@user2965601 user2965601, ваш номер, чтобы вернуть бит обратно, 0x80000000000000, выглядит немного коротким. Я почти уверен, что если вы добавите еще два 0 в конец, он должен начать работать правильно.   -  person jonhopkins    schedule 07.11.2013
comment
@jonhopkins: Да, ты прав. Это работает. Спасибо!   -  person    schedule 07.11.2013
comment
if (x) { do { ...} while (x); } лучше писать как while (x) { ... }.   -  person glglgl    schedule 08.11.2013


Ответы (3)


uint64_t rotate(uint64_t v, int n) {
    n = n & 63U;
    if (n)
        v = (v >> n) | (v << (64-n));
    return v; }

gcc-O3 производит:

.cfi_startproc
andl    $63, %esi
movq    %rdi, %rdx
movq    %rdi, %rax
movl    %esi, %ecx
rorq    %cl, %rdx
testl   %esi, %esi
cmovne  %rdx, %rax
ret
.cfi_endproc

не идеально, но разумно.

person Chris Dodd    schedule 07.11.2013

int storeBit = *i & one;

@ В этой строке вы назначаете 64-битное целое число без знака, вероятно, 4-байтовому целому числу. Я думаю, что ваша проблема связана с этим. В машинах с прямым порядком байтов все будет сложно, если вы будете выполнять неопределенные операции.

person cycrel    schedule 07.11.2013
comment
Ты прав. Это было не очень умно с моей стороны. Я позабочусь об этом. Спасибо. - person ; 07.11.2013
comment
Я думаю, если вы используете компилятор с генерацией предупреждений об ошибках такого рода, это будет вам полезно. - person cycrel; 07.11.2013

if(n > 0) 

не принимает отрицательное значение n

person Luka Rahne    schedule 07.11.2013
comment
Последняя строчка вопроса: Поворот влево отсутствует, так как я его не делал. - person jonhopkins; 07.11.2013
comment
Если я получаю отрицательное значение n, я просто делаю его положительным, а затем начинаю вращение влево. Но код для отрицательного n все равно отсутствует, потому что я еще этого не сделал. - person ; 07.11.2013