看板 C_and_CPP 關於我們 聯絡資訊
誡7加了abs()可能<0的狀況。 ======================================== 07. 你不可以在數值運算、賦值或比較中隨意混用不同型別的數值,而不謹慎考 慮數值型別轉換可能帶來的「意外驚喜」(錯愕)。必須隨時注意數值運算 的結果,其範圍是否會超出變數的型別 錯誤例子: unsigned int sum = 2000000000 + 2000000000; /* 超出 int 存放範圍 */ unsigned int sum = (unsigned int) (2000000000 + 2000000000); double f = 10 / 3; 正確例子: /* 全部都用 unsigned int, 注意數字後面的 u, 大寫 U 也成 */ unsigned int sum = 2000000000u + 2000000000u; /* 或是用顯式的轉型 */ unsigned int sum = (unsigned int) 2000000000 + 2000000000; double f = 10.0 / 3.0; -------------------------------------------------- 錯誤例子: unsigned int a = 0; int b[10]; for(int i = 9 ; i >= a ; i--) { b[i] = 0; } 說明:由於 int 與 unsigned 共同運算的時候,會轉換 int 為 unsigned, 因此迴圈條件永遠滿足,與預期行為不符 -------------------------------------------------- 錯誤例子: (感謝 sekya 網友提供) unsigned char a = 0x80; /* no problem */ char b = 0x80; /* implementation-defined result */ if( b == 0x80 ) { /* 不一定恒真 */ printf( "b ok\n" ); } 說明:語言並未規定 char 天生為 unsigned 或 signed,因此將 0x80 放入 char 型態的變數,將會視各家編譯器不同作法而有不同結果 -------------------------------------------------- 錯誤例子: #include <math.h> int a = -2147483648 ; // 2147483648 = 2 的 31 次方 while (abs(a)>0){ // abs(-2147483648)<0 有可能發生 ++a; } 說明:如果你去看C99/C11 Standard,你會發現long int (4 bytes) 變數的最大/最小值為(被define在limits.h) INT_MIN -2147483647 // compiler實作時最小值不可大於 -(2147483648-1) INT_MAX 2147483647 // compiler實作時最小值不可小於 (2147483648-1) 不過由於32bit能顯示的範圍就是2**32種,所以一般作業系統會把 INT_MIN多減去1,也就是int 的顯示範圍為-2147483648 ~ +2147483647。 當程式跑到abs(-2147483648)>0時,由於int不存在2147483648, 於是正確結果無法被有限的數位顯示(undefined behavior)。 (不只int,其他如long、long long等以此類推) 補充資料: - C11 Standard 5.2.4.2.1, 7.22.6.1 - https://www.fefe.de/intof.html -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.140.52.193 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1463757297.A.596.html ※ 編輯: wtchen (223.140.52.193), 05/20/2016 23:20:46
EdisonX: 表達範圍是complier的事?我以為是補數系統的事… 05/21 09:39
Caesar08: 2**16改成2的16次方。C++沒有** 05/21 09:59
wtchen: 可是SHRT_MIN 應該是compiler (glibc?)定的吧? 05/21 10:01
wtchen: 2**16晚點改,moptt好難用@@ 05/21 10:02
siriusu: 竟然有這個case 05/22 10:55
根據推文修改好了。 ※ 編輯: wtchen (223.137.128.153), 05/22/2016 22:31:36