話說有這樣的一段代碼:服務器
#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。這致使了死循環。