簡單的**,複雜的問題。
環境:vc6sp5,win2kpro
int b = 10; //已經賦值為有效資料
const char * str = "1234567890abcdef"; //已經賦值為有效的字串。
int a = (b - strlen(str) ) / 2;
經過了這樣的計算,a的值究竟是多少?
結果當然不是 (10-16)/2 的 -3,而是乙個天文數字。。。。
a = 2147483645 或者,16進製制的 0x7ffffffd
真正的問題**只有一行,但是結果卻令人不快。
這裡分析一下產生這個問題的原因:
乙個隱含的問題是,strlen的返回值,型別是size_t,也就是unsigned int。這是個無符號型別。
當unsigned int 和 int混合運算的時候,編譯器會認為,unsigned int的表達長度比較長,因而結果的型別是unsigned int。
所以 b - strlen(str) 的結果不是 -6,而是和-6具有相同記憶體布局的unsigned int 值:0xfffffffa,也就是正的4294967290
如果這個數值直接賦值給int,會因為記憶體布局相同,而避免問題的產生--問題存在,但是不產生不良效果。但是隨後的/2操作把問題徹底暴露出來了。。
/2操作可以認為是一次移位,對於無符號型別,移位後高位補0,於是把原本有符號型別賴以利用的符號位清零了。。最終這個數值賦值給int型別的時候,結果就變成了前面提到的那個可怕的數值。。
有符號數字和無符號數字混合運算的時候,存在一些預設的轉換規則,符合這些規則的轉換,都不會引發編譯器警告或者錯誤,因此這類問題是難以覺察的。但是,我們需要經常使用的庫函式太多了,當參與運算的時候,為每個函式呼叫都指定乙個固定型別的返回值,似乎是不可能的任務。因此如果你的程式中充滿各種不同型別的整型運算,那麼還是盡量小心一些吧。。。
關於有符號與無符號的位元組
經歷過幾個時期,一直都用無符串的,總感覺有乙個符號位非常的不靠譜,編譯器什麼時候給你轉一下型別,或者幹了什麼 後來又覺得c嘛,不會管你的到底是 1 還是255,反正都一樣,什麼型別啊,都是浮動,不就是一段記憶體長這樣嘛 後來又變了,覺得unsigned char真是麻煩,還得這麼長或者typedef...
無符號數與有符號數的操作
void sum void 當混合不同型別的變數進行計算時,便可能會發生型別轉換 相同型別的資料在轉換時有規則可循 字元必須先轉換為整數 c語言規定字元型別資料和整型資料之間可以通用 short型轉換為int型 同屬於整型 float型資料在運算時一律轉換為雙精度 double 型,以提高運算精度 ...
有符號int和無符號int的比較
int array define total elements sizeof array sizeof array 0 int main sizeof 返回型別為無符號整型unsigned int,因此 中的total elements值是unsigned int,在比較signed int和uns...