當心有符號數的右移操做

話說有這樣的一段代碼:服務器


#include <stdlib.h>ide


#include <stdio.h>測試




static void divide_by_two(int num)io


{編譯


    while (num) {test


        printf("%d\n", num);循環


        num /= 2;程序


    }im


}static




int main()


{


    int num;


    scanf("%d", &num);




    divide_by_two(num);




    return 0;


}


某天,一個剛畢業的朋友——沒有貶低應屆生的意思哦~~~,開始負責維護這段代碼。他呢,看到num /= 2,想起課程上講過,整數右移一位,就等於除於二,而且右移操做比除法運算要高效的多。因而將 num /=2 改成了 num = num>>1。




代碼變爲


#include <stdlib.h>


#include <stdio.h>




static void divide_by_two(int num)


{


    while (num) {


        printf("%d\n", num);


        num = num>>1;


    }


}




int main()


{


    int num;


    scanf("%d", &num);




    divide_by_two(num);




    return 0;


}


編譯成功後,固然不能忘了測試:


[xxx@xxx-vm-fc13 test]$ ./a.out


10


10


5


2


1


[xxx@xxx-vm-fc13 test]$ ./a.out


3


3


1


這位朋友對於結果很滿意,因而將改動提交到了服務器,下班回家~~~




結果次日就有同事來找他,說他的程序陷入了死循環:


[xxx@xxx-vm-fc13 test]$ ./a.out


-5


-5


-2


-1


-1


-1


。。。。。。


-1


這位朋友剛參加工做,第一次提交改動,就形成了這樣的結果,天然很緊張。不是右移一位就等於除以2嗎?到底是怎麼回事呢?雖然暫時不知道,也只能將改動rollback回去。




那麼究竟是什麼緣由呢?沒錯,右移一位就等於除以2,可是這裏須要加一個條件,這裏指的是正數。而對於有符號整數,且其值爲負數時,在C99標準中對於其右移操做的結果的規定是implementation-defined.




在Linux上的GCC實現中,有符號數的右移操做的實現爲使用符號位做爲補充位。所以-1的右移操做仍然爲0xFFFFFFFF。這致使了死循環。

相關文章
相關標籤/搜索