Unsigned vs. Signed
在定義整數變數的型態的時候可以加上 unsigned 或是 signed, 例如
unsigned char
unsigned short (int)
unsigned long (int)
unsigned int
----------
signed char
signed short (int)
signed long (int)
signed int
--------------
上面 signed 有加和沒有加是一樣的意義
加上 unsigned 以後,
1. 所需要的資料儲存空間和沒有加 unsigned 時是一樣的
2. 在使用 printf() 列印時基本上你必須分清楚
unsigned 有影響到的是參數的傳遞, 使用 %d 或是
%u 基本上是看程式設計者自己的選擇
int i=-1;
printf("%d %u\n", i, i);
會印出
-1 4294967295
unsigned int i=-1;
printf("%d %u\n", i, i);
也會印出
-1 4294967295
char i=-1;
printf("%d %u\n", i, i);
還是會印出
-1 4294967295
但是
unsigned char i=-1;
printf("%d %u\n", i, i);
則會印出
255 255
這不是 %d 和 %u 的問題, 而是
參數傳遞時資料轉換的問題 (見下面第 3 項)
不一樣的地方有下面幾個
1. 資料的範圍基本上加上 unsigned 以後會變成 2 倍
2. 程式裡比較大小的時候
int i=1;
int j=-1;
if (i>j) printf("i>j\n");
else printf("i<=j\n");
你會發現結果是 i>j
unsigned int i=1;
int j=-1;
if (i>j) printf("i>j\n");
else printf("i<=j\n");
你會發現結果是 i<=j
也就是說 signed 和 unsigned 在比較的時候 compiler
會把 signed int 自動當成 unsigned int 來比較
2. 資料轉換的時候 (或是函式呼叫的時候)
char i = -128;
int j = i;
變數 i 裡面的資料只有 1 個位元組, 要放進
變數 j 裡面的時候需要做 sign extension
也就是多出來的 3 個位元組 (24 個 bit) 都要
填入原來 i 的 sign bit (第 8 個 bit)
以上例來說 (用二進位表示)
i: 10000000
j: 11111111 11111111 11111111 10000000
unsigned char i = -128;
int j = i;
由 unsigned 轉為 signed 時前面一率補 0
用二進位表示
i: 10000000
j: 00000000 00000000 00000000 10000000
char i = -128;
unsigned int j = i;
還是做 sign extension
用二進位表示
i: 10000000
j: 11111111 11111111 11111111 10000000
函式呼叫的時候會做型態的轉變, 例如
void fun(int x)
{
...
}
呼叫時如果用
unsigned char i=-1;
fun(i);
就會自動做轉換
呼叫 printf 時會做 default promotion
因為 printf 函式的定義如下
int printf(const char *format, ...)
其中的 ... 代表可以接受任意型態和個數
的參數, 所有小於四個位元組的整數資料一律
轉換為四個位元組, 浮點數一律轉為八個位元組
所以在轉換時也會根據傳入參數是否有 unsigned
來做 sign extension
4. 可能還有其它不同點我現在一下子想不起來