以下例子取自《深入理解計算機系統》。
考慮如下的C語言代碼:
1 #include<stdio.h> 2 3 typedef unsigned char* byte_pointer; 4 5 void show_bytes(byte_pointer pointer, int size){ 6 int i = 0; 7 for (i = 0; i < size; ++i){ 8 printf("%.2x", pointer[i]); 9 } 10 } 11 12 int main(){ 13 short sx = -12345; 14 unsigned uy = sx; 15 printf("uy = %u:\t", uy); 16 show_bytes((byte_pointer)&uy, sizeof(unsigned)); 17 printf("\n"); 18 }
該程序在小端法的機器上會產生如下輸出:uy = 4294954951: c7cfffff
這表明當把short轉換成unsigned 時,我們先改變大小,之後在完成從有符號到無符號的轉換。也就是說(unsigned)sx等價於(unsigned)(int)sx,求值得到4294954951,而不等價於(unsigned)(unsigned short)sx,後者求值得到53191。事實上,這個規則是C語言標准要求的。
另外,當執行一個運算時,如果它的一個運算數是有符號的而另一個是無符號的,那麼C語言會隱式地將有符號參數強制類型轉換為無符號參數,並假設這兩個數都是非負的,來執行這個運算。這種方法對於標准的算數運算並無多大差異,但是對於<和>這樣的關系運算符來說,它會導致非直觀的結果。
例如對(-1 < 0U)這個表達式求值,其結果為0。因為第二個運算數是無符號的,第一個運算數會被隱式地轉換為無符號數,因此表達式就等價為(4294967295U < 0U),這個答案顯然是錯的。
基於同樣的理由,我們考慮一下代碼:
1 double sum_elements(double a[], unsigned length){ 2 int i; 3 double result = 0; 4 for (i = 0; i <= length - 1; ++i){ 5 result += a[i]; 6 } 7 return result; 8 }
當傳入的length=0時,會產生越界錯誤。