SDCC 有號無號型別轉換問題

Posted by: 邱小新 at 下午4:51 in
void main(void) { unsigned char a=-12; char b=-3; printf("\n\r-12 / -3 = %d", a/b); }

當執行上述程式碼時,理論上輸出值應為 "-12 / -3 = 4",但是輸出的值卻為 "-12 / -3 = -81"。為什麼會如此呢?主要是因為 SDCC 在做型別轉換時出了點問題。如下所示:

  1. (int) (unsigned char) -12 / (int) (signed char) -3 =
  2. (int) (unsigned char) 0xf4 / (int) (signed char) 0xfd =
  3. (int) 0x00f4 / (int) 0xfffd =
  4. (int) 244 / (int) -3 =
  5. (int) -81 = (int) 0xffaf;

只要改成下列程式就沒有問題了。

void main(void) { unsigned char a=-12; char b=-3; printf("\n\r-12 / -3 = %d", (char)a/b); }


void main(void) { unsigned short n=100; int l = -1; printf("sizeof(int) %d\n\r", sizeof(int)); if (n > l) printf("%u > %d\n\r", n, l); else printf("%u <= %d\n\r", n, l); }

當執行上述程式碼時,理論上輸出值應為 "100 > -1",但是輸出的值卻為 "100 <= -1"。但是在 linux 用 gcc 編譯執行的結果卻是 "100 > -1"。為什麼會如此呢?主要是因為 SDCC int 為 2bytes 而 gcc int 為 4bytes。

在 SDCC 中 unsigned short 與 int 都是 2bytes,根據一般算術型別轉換,unsigend 級別比較低時,signed 的資料型別 bit 數跟 unsigned 一樣多,會把 signed 轉成 unsigned,也就是 -1 變成 65535。如此 100 當然小於 -1 (65535) 囉。




一般算術型別轉換規則

  1. 整數型別的級別排序是 char < short < int < long < long long。
  2. 兩個運算元的型別相同時,不做轉換。
  3. 兩個運算元的型別不同時,兩邊都一樣是 signed 或 unsigned 的話,就轉換成高級別的型別。
  4. 兩個運算元的型別不同時,一個是 signed,一個 unsigned 的話。
    unsigned 這邊的級別比較高或相等時,會把 signed 轉成 unsigned。
    unsigend 級別比較低時,signed 的資料型別 bit 數比另一邊多時,會把 unsigned 轉成 signed,反之會把 signed 轉成 unsigned。

0 意見

張貼留言