理解c中的运算符和位移

时间:2012-03-08 03:58:29

标签: c++ c

以下程序计算此表达式的值

m = i /16 + j *128-17 + k *2- l /32 , if i > j + 2 * k else 
m = i /16 + j *128-17 + k *2 + l /32
编写此程序的人没有使用乘法和除法运算符,可能有人向我解释这里真的发生了什么,我的意思是程序中的(*和/)在哪里?为什么或者目的是什么?左右移动?

#include <stdio.h>
#include <cstdlib>

int main(){
    unsigned int i, j, k, l, m;
    printf("i = "); scanf("%d", &i);
    printf("j = "); scanf("%d", &j);
    printf("k = "); scanf("%d", &k);
    printf("l = "); scanf("%d", &l);
    if (i > j + (k << 1)) 
        m = (i >> 4) + (j << 7) - 17 + (k << 1) - (l >> 5);
    else
        m = (i >> 4) + (j << 7) - 17 + (k << 1) + (l >> 5);
    printf("m = %d\n", m);
    system("pause");
}

3 个答案:

答案 0 :(得分:6)

二进制数中的每个数字是前一个数字的2倍:

   1    Binary = 1 Decimal
  10    Binary = 2 Decimal
 100    Binary = 4 decimal
1000    Binary = 8 decimal

因此,如果将位1向左移位数字,则相当于乘以2.

相反地将1个位置向右移动就像是除以2。

如果您移动多个位置,则只需增加2的幂。因此,将n位置向左移动就像乘以2^n一样,将n位置向右移动就像除以2^n等。

   i / 16
=> i / (2^4) 
=> 1 >> 4      // division right shift

   j * 128
=> j * (2^7)
=> j << 7      // multiplication left shift

   k * 2
=> k * (2^1)
=> k << 1      // multiplication left shift

   l / 32
=> 1 / (2^5) 
=> l >> 5      // division right shift

绝对没有理由这样做。
事实上,我会说在normal情况下这是一种可怕且完全不好的做法;如果编译器认为这将是一个好处并且缺点(正如您所注意到的那样)会使代码更难以阅读,编译器将自动执行此优化。

如果您知道编译器是坏的并且不这样做那么可能值得做(但可能只是)。

答案 1 :(得分:4)

将整数m向右移位整数n只是意味着将m除以2除以n的幂,向左除以将它们相乘

所以i / 16相当于i >> 4,因为2^416,其余的表达式如下:)

答案 2 :(得分:1)

正如其他人所提到的,位移是另一种乘以或除以2的幂的方法。对于除法,重要的是要记住它正在进行整数除法,也就是说,余数将会丢失。

你想要做这样的事情的原因是因为速度。 CPU可以比它的乘法更快地进行位移。但是,虽然我不是这方面的专家,但我必须相信你的编译器无论如何都会进行优化,因此我不建议仅仅因为这个原因而降低代码的可读性。 :)