C語言中的隱式轉換
為了定義轉換規則,C99允許每個整數型別具有"整數轉換等級"。下面按從最高階到最低階的順序排列。
(1)long long int、usigned long long int
(2)long int、unsigned long int
(3)int 、unsigned int
(4)short int 、unsigned short int
(5)char、signed char、unsigned char
(6)_Bool
比較轉換規則如下:
如果兩個運算元型別相同,過程結束,否則依次嘗試下面的規則:
(1):如果兩個運算元都是有符號型或者都是無符號型,將整數轉換等級較低的運算元轉換為等級較高的運算元型別;
(2):如果無符號運算元的等級高於或等於有符號運算元的等級,將有符號運算元轉換為無符號運算元的型別。比如比較unsigned int 與int,將int提升為unsigned int.
(3):如果有符號運算元型別可以表示無符號運算元型別的所有值,將無符號運算元轉換為有符號運算元的型別。比如比較int 與unsigned short int,將unsigned short int提升為int
(4):將兩個運算元都轉換為與有符號運算元的型別相對應的無符號型別
stackoverflow上針對這一轉換規則的一個回答ofollow,noindex" target="_blank">stackoverflow
.
幾個容易犯錯的地方:#include <stdio.h> #include <stdlib.h> int main() { int a = -1; unsigned int b = 1; if(a > b) printf("a > b, a = %d, b = %u\n", a, b); else printf("a <= b, a = %d, b = %u\n", a, b); exit(0); }
按照我們上面的規則比較unsigned int 與int 時將int 提升為unsigned int ,由於-1的底層表示為全一,因此轉換為unsigned int時將為UINT_MAX即4294967295.因此b>a.
編譯時新增選項-Wsign-compare可以檢測出該問題。[root@centos-linux-7 workspace]# gcc -Wsign-compare-g -o compare compare.c compare.c: In function ‘main’: compare.c:9:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if(a > b)
在csapp書中第二章有幾個經常犯錯的例子:
float sum_element(float a[],unsigned length) { int i; float result = 0; for(i=0;i<=length-1;i++) result+=a[i]; return result; }
size_t strlen(const char*s); int strlonger(char *s,char *t) { return strlen(s)-strlen(t)>0; }
都是型別惹的禍——小心unsigned