Печать битов в длинном длинном номере (C++)

Я хочу напечатать все биты длинного длинного числа. Когда я делаю это в main(), все в порядке, но в функции printBits() (где код один и тот же) есть дополнительный 1 на 32-й бит.

Код:

#include <iostream>

void printBits(long long number)
{
    std::cout<<number<<" -> ";
    for (char i=63; i>=0; --i)
    {
        std::cout<<(bool)(number&(1<<i));
    }
    std::cout<<std::endl;
}

int main()
{
    long long number=1;

    std::cout<<number<<" -> ";
    for (char i=63; i>=0; --i)
    {
        std::cout<<(bool)(number&(1<<i));
    }
    std::cout<<std::endl;

    printBits(number);

    return 0;
}

Результат:

1 -> 0000000000000000000000000000000000000000000000000000000000000001
1 -> 0000000000000000000000000000000100000000000000000000000000000001

Process returned 0 (0x0)   execution time : 0.012 s
Press any key to continue.

3 ответа

Решение

Литерал 1 по умолчанию является целым числом. Примените это долго долго, чтобы решить проблему.

std::cout<<(bool)(number&(((long long)1)<<i));

Причина разных результатов в том, что компилятор (здесь clang 6.0) может выдавать другой код в основной функции и в printBits,

В main известно, что number всегда 1 и никогда не меняется. Также "очевидно", что это может произвести только один 1 на выходе. Таким образом, оптимизатор переписывает цикл следующим образом:

for (char i=64; i > 0; --i)
{
    std::cout<< (i == 1 ? 1 : 0);
}

Смотри, мама, без сдвигов!

Сборка выглядит так

012B13CC  mov         bl,40h    ; i = 40h = 64  
012B13CE  xchg        ax,ax     ; nop to align the loop
main+30h: 
012B13D0  xor         eax,eax  
012B13D2  cmp         bl,1      ; i == 1?
012B13D5  mov         ecx,esi  
012B13D7  sete        al  
012B13DA  push        eax  
012B13DB  call        edi       ; edi -> operator<<
012B13DD  dec         bl  
012B13DF  jg          main+30h (012B13D0h)  

В printBits он не может оптимизировать этот путь, так как функция может быть вызвана из другого места. Так что там он выполняет сдвиг (с ошибочным результатом).

Как показывает ответ Cpp plus 1, вам нужно изменить (по умолчанию int) литерал 1 к длинному длинному буквальному 1LL или же 1ll,

Тем не менее, вам может быть лучше использовать std::bitset вместо вашей функции:

#include <bitset>
long long number = 1;  // int number = 1;  also works
std::bitset<64> bits(number);
std::cout << number << " -> " << bits << std::endl;

выходы:

1 -> 0000000000000000000000000000000000000000000000000000000000000001

Причина, по которой вы получаете этот вывод, заключается в том, что для конкретного используемого вами оборудования / компилятора:

a << x Работа работает следующим образом: a << (x mod (8 * sizeof(a)), Поэтому для 1 ты получаешь 1 << (x mod 32), Это означает, что на 32-й итерации цикла:

std::cout << (bool)(number & (1 << 32));
// becomes
std::cout << (bool)(number & (1 << 0));
// printing '1'
Другие вопросы по тегам