在kmp.cpp中的迴圈,迴圈判斷下標(int型別)與std::string::size_type型別比較發生了迴圈只執行一部分的問題。
int i = j = 0
while (i < s.size() && j < p.size())
在這段**當中,出現了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==i
為true
,而且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
*/
可以看出,應該是從右邊開始進行邏輯與比較,大小為小的一方。 C中有符號數與無符號數轉化之間的危險
無符號數與有符號數之間存在著很多細節問題,稍有不慎就可能導致程式出現不可預料的錯誤。如果說是在長度相同的數值型別之間相互轉化或者向長度比較短的資料轉化是沒有問題的,結果都是已定義的 多餘的位將被簡單的丟棄。但是,一旦需要向長度更長的資料型別轉化這個問題就會變得十分蹊蹺。例如編譯器在轉化char型別到...
C語言有符號數與無符號數之間的轉換
無符號數 不存在正負之分,所有位都用來表示數的本身。有符號數 最高位用來表示數的正負,最高位為1則表示負數,最高位為0則表示正數。1 無符號數 有符號數 看無符號數的最高位是否為1,如果不為1 為0 則有符號數就直接等於無符號數 如果無符號數的最高位為1,則將無符號數取補碼,得到的數就是有符號數。以...
C語言有符號數與無符號數之間的轉換
寫在前面 以下內容是我的愚見,如有不對,歡迎拍磚。無符號數 不存在正負之分,所有位都用來表示數的本身。有符號數 最高位用來表示數的正負,最高位為1則表示負數,最高位為0則表示正數。1 無符號數 有符號數 看無符號數的最高位是否為1,如果不為1 為0 則有符號數就直接等於無符號數 如果無符號數的最高位...