天天看點

C語言signed和unsigned的使用與注意事項

作者:霸都嵌入式

C語言中,signed和unsigned是兩個類型修飾符,它們可以用來修飾整數類型,表示變量的符号屬性。signed表示變量是有符号的,可以存儲正數和負數;unsigned表示變量是無符号的,隻能存儲非負數。在使用signed和unsigned時,需要注意以下幾個方面:

signed和unsigned的使用方法

- signed和unsigned可以修飾int、short、long和long long等整數類型。例如:

signed int a; //有符号整型
unsigned int b; //無符号整型
signed short c; //有符号短整型
unsigned short d; //無符号短整型
signed long e; //有符号長整型
unsigned long f; //無符号長整型
signed long long g; //有符号long long類型
unsigned long long h; //無符号long long類型           

- signed是預設的,如果不加任何修飾符,變量就是有符号的。是以,int等價于signed int,short等價于signed short,long等價于signed long,long long等價于signed long long。例如:

int i; //等價于signed int i;
short j; //等價于signed short j;
long k; //等價于signed long k;
long long l; //等價于signed long long l;           

- unsigned則需要顯式給出,表示變量沒有符号位。例如:

unsigned int m; //無符号整型
unsigned short n; //無符号短整型
unsigned long o; //無符号長整型
unsigned long long p; //無符号long long類型           

- 對于long和long long常量,可以使用字尾直接給出unsigned的屬性。例如:

120L; //L字尾表示long常量
120LU; //LU字尾表示unsigned long常量
120LLU; //LLU字尾表示unsigned long long常量
120ull; //ull字尾也表示unsigned long long常量           

signed和unsigned的差別

- signed和unsigned的差別主要在于是否把存儲的某一位看做符号位。對于n位的二進制數,如果是有符号的,最高位是符号位,0表示正數,1表示負數;如果是無符号的,沒有符号位,所有位都表示數值。

- 有符号數在計算機中用補碼表示。正數的補碼是其本身;負數的補碼是其絕對值取反加一。例如:

8位有符号數5的補碼為:00000101
8位有符号數-7的補碼為:11111001(|-7|=7 -> 00000111 -> 11111000 -> +1)           

- 無符号數在計算機中用原碼表示。原碼就是二進制數本身。例如:

8位無符号數5的原碼為:00000101
8位無符号數7的原碼為:00000111           

- 是以,同樣一個二進制數,在不同的類型下可能表示不同的值。例如:

8位二進制數11111001,在有符号類型下表示-7,在無符号類型下表示249。           

- 同樣長度的有符号數和無符号數能夠存儲的數值範圍也不同。對于n位的二進制數,如果是有符号的,最小值為-2^(n-1),最大值為2^(n-1)-1;如果是無符号的,最小值如果是無符号的,最小值為0,最大值為2^n-1。例如:

8位有符号數的範圍是-128 ~ 127
8位無符号數的範圍是0 ~ 255           

signed和unsigned的注意事項

- 在使用signed和unsigned時,需要注意以下幾個方面:

- 在進行算術運算時,如果有符号數和無符号數混合運算,會發生隐式類型轉換,導緻結果不正确或者溢出。例如:

int a = -1;
unsigned int b = 1;
printf("%d\n", a + b); //輸出0,因為a被轉換為無符号數,其值為4294967295(2^32-1)
printf("%u\n", a + b); //輸出4294967296,因為結果溢出了無符号數的範圍           

- 在進行比較運算時,如果有符号數和無符号數混合比較,也會發生隐式類型轉換,導緻結果不正确。例如:

int a = -1;
unsigned int b = 1;
printf("%d\n", a < b); //輸出0,因為a被轉換為無符号數,其值為4294967295(2^32-1),大于b
printf("%d\n", a > b); //輸出1,同理           

- 在進行位運算時,如果有符号數和無符号數混合運算,也會發生隐式類型轉換,導緻結果不正确。例如:

int a = -1;
unsigned int b = 1;
printf("%d\n", a & b); //輸出1,因為a被轉換為無符号數,其值為4294967295(2^32-1),與b按位與後仍然是1
printf("%d\n", a | b); //輸出-1,因為結果被轉換為有符号數,其值為4294967295(2^32-1),按照補碼規則表示-1           

- 在進行指派運算時,如果有符号數和無符号數混合指派,也會發生隐式類型轉換,導緻結果不正确。例如:

int a = -1;
unsigned int b = 1;
a = b; //a的值變為1
b = a; //b的值變為4294967295(2^32-1)           

- 為了避免這些問題,在使用signed和unsigned時,應該盡量保持類型一緻,或者使用強制類型轉換來明确表達意圖。例如:

int a = -1;
unsigned int b = 1;
printf("%d\n", (int)(a + b)); //輸出0,強制将結果轉換為有符号數
printf("%u\n", (unsigned int)(a + b)); //輸出4294967296,強制将結果轉換為無符号數
printf("%d\n", (int)a < (int)b); //輸出1,強制将兩個操作數都轉換為有符号數
printf("%d\n", (unsigned int)a > (unsigned int)b); //輸出0,強制将兩個操作數都轉換為無符号數           

系列文章持續更新,如果覺得有幫助請點贊+關注!

繼續閱讀