1. 程式人生 > >C++有/無符號數字型別之間的比較

C++有/無符號數字型別之間的比較

在kmp.cpp中的迴圈,迴圈判斷下標(int型別)與std::string::size_type型別比較發生了迴圈只執行一部分的問題。

int i = j = 0
while (i < s.size() && j < p.size())
{
// some codes may make j -1;
}

在這段程式碼當中,出現了j < p.size()但是卻不執行迴圈的情況。原因是當j為-1的時候,j > p.size(), 因為unsigned/signed型別。

string s = "ababababababababababababababababababcaHello world!";
int i = -1;
cout << "i < s.size():" << (i < s.size()) << endl;
size_t ui = i;
cout << "ui:" << ui << endl;
cout << "ui == i:" << (ui == i) << endl;
/* ouputs:
i < s.size():0
ui:18446744073709551615
ui == i:1
*/

string::size()型別是無符號型別。所以使用關係運算符會出現問題。但是繼續觀察剩下部分demo,發現ui==itrue,而且ui的位元組隨著32/64位機器改變,底層的比較依舊為true,這是一個feature。應該設計機組的底層實現的知識。負數的二進位制表達。

檢視《計算機組成與設計:硬體/軟體介面(亞洲版)》2.4 signed and unsigned numbers部分知識得到: Negating this number by inverting the bits and adding one.

所以-1對於int32的二進位制為:00000...001 -> 111...1110, + 1, 11111...111,32個1。對於size_t ui = 18446744073709551615 為2 ^ 64 - 1, 也就是111111...1111, 64個1,所以他們被判斷相等。

unsigned long ul = 0xFFFFFFFFFFFFFFFF; // 16個F, 16^16-1
int si = -1;
cout << ul << endl;
cout << "si==ul:" << (ul == si) << endl;
/*
18446744073709551615
si==ul:1
*/

可以看出,應該是從右邊開始進行邏輯與比較,大小為小的一方。