C中的除法,商和余數的大小、符號如何確定
阿新 • • 發佈:2018-06-03
spa 匯編碼 來看 div 最大整數 () 以及 有時 取余
對於C中的除法,商和余數的大小、符號是如何確定的呢?在C89中,只規定了如果兩個數為正整數,那麽余數的符號為正,並且商的值是接近真實值的最大整數。比如5 / 2,那麽商就是2,余數就是1。但是,C89裏面對於被除數和除數裏面,有負整數時,商的大小以及余數的符號沒有做出明確的規定,而只是說這依賴於具體實現。在Windows下(是Intel匯編指令),看如下如下例子:
int main() { int a = -5; int b = a / 3; }
接下來看匯編碼:
; 1 : int main() { push ebp mov ebp, espsub esp, 8 ; 2 : int a = -5; mov DWORD PTR _a$[ebp], -5 ; fffffffbH ; 3 : int b = a / 3; mov eax, DWORD PTR _a$[ebp] cdq mov ecx, 3 idiv ecx ;idiv執行有符號的除法,並且余數的符號和被除數一樣 mov DWORD PTR _b$[ebp], eax ; 4 : }
匯編碼中,最重要的就是idiv指令,這個指令運行後的結果是余數的符號會保持和被除數一樣,同時,對於除法來說,余數的絕對值要小於除數的絕對值,這樣,我們就可以確定商、余數的大小以及符號。對於上面的例子-5 / 3來說,商就是-1,余數就是-2。
有時,由於除法可以轉換成加減法以及算數右移來執行,匯編碼不會用到idiv指令(這可以看成是一種優化),但是結果不會有影響,比如看下面的-5 / 2的匯編指令,就沒有用到idiv,但是結論和上面一樣,商是-2,余數是-1:
; 1 : int main() { push ebp mov ebp, esp sub esp, 8 ; 2 : int a = -5; mov DWORD PTR _a$[ebp], -5 ; fffffffbH ; 3 : int b = a / 2;mov eax, DWORD PTR _a$[ebp] cdq sub eax, edx sar eax, 1 ;算數右移操作 mov DWORD PTR _b$[ebp], eax ; 4 : ; 5 : }
上面的結論在Linux下(AT&T風格的匯編)同樣成立,雖然匯編碼和Intel匯編不一樣。
另外,C89中規定,對於%取余運算符,只適用於整型
C中的除法,商和余數的大小、符號如何確定