2016-07-24 4 views
3

Я бег следующей программы: (URL: http://ideone.com/aoJoI5)Понимание того, как долго длится int int?

#include <iostream> 
    #include <cmath> 
    using namespace std; 
    int main() 
    { 
    long long int N=pow(2, 36); 
    cout << N <<endl; 
    int count = 0; 
    cout << "Positions where bits are set : " << endl; 
    for(int j=0; j<sizeof(long long int)*8; ++j){ 
    if(N&(1<<j)){ 
     ++count; 
     cout << j << endl; 
    } 
    } 
    return 0; 
} 

Эта программа дает мне результат, как:

68719476736 
Positions where bits are set : 
31 
63 

Теперь, как я использую N = 2^36, что означает 36-й бит должны быть 1 и ничего больше, но почему программа дает мне позицию 31 и 63? что-то не так с моей программой?

У меня есть одно замечание, что если мы используем N = 2^{exp}, где exp> = 32, он всегда дает позиции для заданного бита равным 31 и 63. Может кто-нибудь объяснить, почему это происходит?

+3

'1 << j' может привести к слишком большому сдвигу. Вместо этого следует использовать '1ull << j'. – MikeCAT

+0

@MikeCAT Спасибо, что сработал. – LovelyGuyAnSh

+2

@MikeCAT: Пожалуйста, не используйте раздел комментариев для ответов. Если вы не хотите представителя, вы можете вернуть сообщество, наделив его. –

ответ

6

Если int является 32-разрядным, 1<<j будет делать сдвиг слишком много, и вызвать неопределенное поведение.

Вот мое предположение о причине:

  1. Когда j становится 31, то 1 бит приходит знаковый бит.
  2. Видя бит знака равно 1, для расчета побитовое И с N, значение по знаку, так что биты с 31 по 63-й (0-происхождения) становятся 1.
  3. 36-й бит (0-происхождения) в N - 1, поэтому результат побитового И будет отличным от нуля.
  4. Условие оценивается как истинное и число печатается.
  5. Когда j равно 63, если вы используете процессор IA-32, ширина, которую нужно сдвинуть, замаскирована на 5 бит, поэтому она будет интерпретирована как 31, и произойдет то же самое.

Чтобы избежать этого неопределенного поведения, использовать unsigned long long значение сдвиг, как 1ull<<j. Обратите внимание, что использование long long не является хорошим, потому что смещение 1 бит для подписания бит вызывает неопределенное поведение.

Смежные вопросы