zoukankan      html  css  js  c++  java
  • C中的除法,商和余数的大小、符号如何确定

    对于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, esp
        sub    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中规定,对于%取余运算符,只适用于整型

  • 相关阅读:
    speex库音频降噪(含代码)
    语音增强(降噪)之一——谱减法
    CUDA与OpenGL互操作
    二维图像的三维旋转
    迷惑很久,仅以个人想法谈谈MVC架构,希望大家多给点意见
    Less使用心得
    js实现蛇形矩阵
    H5天气查询demo(二)
    HTML5 Shim
    html5发展的里程碑事件
  • 原文地址:https://www.cnblogs.com/chaoguo1234/p/9130036.html
Copyright © 2011-2022 走看看