這兩天的工作需要涉及到對無符合數,有符號數作混合運算。
作了一些實驗,發現自己寫了這麼多年的程式,以前對於符號數計算相關的理解居然仍存在一些盲點。
有符號數與無符號數混合運算可能有三種混合方式
1。運算元全為有符號數
如:int a = -1;
int b = 2;
a + b;
2。運算元全為無符號數
如:unsigned int a = (unsigned int)-1;
unsigned int b = 2;
a + b;
3。運算元混合了有符號數,無符號數
如:int
a = -1;
unsigned int b = 2;
a / b;
情形1和2就不用說了,因為運算中涉及的都是相同符號特徵的運算元,計算過程中不會引起歧義。
而對於情形3,由於涉及到了符號特性相異的運算元,情況就有些複雜了。
這裡先說一下,對於有些運算操作,是要區分有符號與無符號的情況的。比如有符號的除法與無符號
的除法,有符號的取模運算與無符號的取模運算,其計算語意是不同的,具體來說,有符號的除法在x86
平台上對應的彙編指令是idiv,而無符號的除法對應的則是div。
而對於另外一些操作運算,則是不區分有符號與無符號的,比如,加法,減法,乘法運算。
int main()
對這一段程式呼叫g++ -s,生成相應的彙編檔案,就會發現:
加法運算,無論是有符號還是無符號,對應的都是addl指令,
減法運算
,對應的都是subl指令,
乘法運算
,對應的都是imul指令,
有符號除法
運算對應的是idiv指令,無符號除法對應的則是div指令,
有符號數取模運算會用到idiv指令,無符號取模用的則是div指令。
所以回到初始的問題,情形1和2的行為是容易預期的,因為所有運算元都具有同樣的符號特性,直接就
可以得出採用相應符號特性的運算型別。
對於情形3,因為涉及到不同符號數的混合計算,在計算之前需要先對運算元進行規整化的動
作,規整的原則就是如果運算元中存在至少乙個無符號數,則所有運算元都被轉化為無符號數,
運算操作也採用相應的無符號操作符進行,計算完的結果也是乙個無符號數。
舉例來說:
(unsigned int)a / (signed int)b會採用無符號除法進行,其實質相當於
(unsigned int)a / (unsigned int)b
計算結果也是乙個無符號數。
再進一步,對於運算-2 / -1,如果採用有符號數運算,結果是1,採用無符號數運算,結果則是0。
所以(signed int)(-2) / (unsigned int)(-1)的結果就是0了。
除法,取模這樣的操作符在不同的上下文語境裡對應的語義動作也有所不同,而且這種差異還不
同於c++裡的操作符過載在語言級別可見,而是要到更底層的組合語言級別才可見,這多少就有
一些tricky,也容易誘使程式設計師犯錯了。如果有機會我來設計一門語言,我想自己會盡量避免引
入這種tricky的東西的。
有關C語言中有符號 無符號數混合運算的小問題
分類 c語言知識 2012 03 28 00 47 157人閱讀收藏 舉報語言c彙編 n2div工作 這兩天的工作需要涉及到對無符合數,有符號數作混合運算。作了一些實驗,發現自己寫了這麼多年的程式,以前對於符號數計算相關的理解居然仍存在一些盲點。有符號數與無符號數混合運算可能有三種混合方式 1。運算...
C語言中 有符號數 無符號數 整數溢位
c語言中存在兩種整數算術運算,有符號型和無符號型。無符號數運算 所有無符號數運算都是以2的n次方為模,n是結果中的位數 所以它不存在運算時的沒有那種所謂的 溢位 當它超過範圍時,從零開始重新計數!當乙個無符號數和有符號數相加的時候,有符號數會自動轉化為無符號數參與運算!有符號數運算 是可能發生 溢位...
C語言中 有符號數 無符號數 整數溢位
includevoid main 這個的結果134,而不是我之前認為的很大的正數,實際上需要注意的是 1 0xffffffff 被提公升為unsigned int後是乙個差1就溢位的unsigned int,所以相加後結果是134。但是如果l 10000,那麼結果就真是乙個很大的正數了,因為不涉及溢...