關於操作有符號數的溢位問題
在計算機中,數值的二進位制表示方法主要有:原碼、反碼和補碼。通常取最高位為符號位,0表示正數,1表示負數。正數的原碼、反碼、補碼一樣。而負數的原碼最高位取1,數值位取負數絕對值的二進位制值;反碼的符號位為1,其餘位取反;補碼的符號位為1,其餘位取反加1。
在32位計算機中,有符號字元型變數的取值範圍是-27 ~ 27-1,有符號整型變數的取值範圍是-215~ 215-1,如果將有符號整型變數賦給有符號字元型變數,則高位被截斷,保留低八位。
看一個例子:
#include<stdio.h> #include<string.h> int main() { char a[1000]; int i; for(i = 0; i < 1000; i++) { a[i] = -1 - i; } printf("%d\n", strlen(a)); return 0; }
語句a[i] = -1 – i ;將有符號整型變數賦給有符號字元型變數,當0 <= i <=127時,不會溢位,a[i]從-1變到-128,當i = 128時,- 1 - i = -129。-129的原碼形式是:
1000 0000 0000 0000 0000 00001000 0001;補碼形式是
1111 1111 1111 1111 1111 11110111 1111;此時將其賦給signed char型別的a[128]時,發生溢位,只保留低八位0111 1111,即127。之後隨著i的增加,a[i]從127逐漸向0靠近,當I = 254時,-1 – I =-255,補碼錶示是:1111 1111 1111 1111 1111 1111 0000 0001,此時a[254] = 1。當i = 255時,a[255] = 0,即將ASCII碼為0的值賦給字元型陣列元素a[255]。隨後a[i]又是從-1 ~ -128,再從127 ~ 0之間反覆變化。
而strlen函式是求取字串的實際長度,當遇到第一個空字元’\0’時,返回,所以strlen(a) = 255。
PS:空字元’\0’(ASCII碼值為0)、零字元’0’(ASCII碼值為48)。
2014年8月10日星期日