Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 位移位和算术运算之间的区别是什么? intanumber; a数量=aValue/2; a数量=aValue>>1; aNumber=aValue*2; a数量=aValue>2; aNumber=aValue*8; aNumber=aValue_C++_C_Objective C_Bit Manipulation - Fatal编程技术网

C++ 位移位和算术运算之间的区别是什么? intanumber; a数量=aValue/2; a数量=aValue>>1; aNumber=aValue*2; a数量=aValue>2; aNumber=aValue*8; aNumber=aValue

C++ 位移位和算术运算之间的区别是什么? intanumber; a数量=aValue/2; a数量=aValue>>1; aNumber=aValue*2; a数量=aValue>2; aNumber=aValue*8; aNumber=aValue,c++,c,objective-c,bit-manipulation,C++,C,Objective C,Bit Manipulation,在您给出的示例中,这两个函数在功能上是等效的(除了最后一个,如果您在计算速度有影响的紧循环环境中进行大型计算,则应阅读aValue*8==aValue),使用位运算(被认为比算术运算快)当它的幂为2个数字(2^x)时,最好使用移位-它只是“推”位。(1次汇编操作,而不是2次除法) 有哪种语言的编译器可以进行这种优化?位移位是一种“接近金属”的操作,在大多数情况下,它不包含任何关于您真正想要实现什么的信息 如果你想把一个数字除以二,那么一定要写x/2。它恰好是通过x>>1实现的,但后者隐藏了意图

在您给出的示例中,这两个函数在功能上是等效的(除了最后一个,如果您在计算速度有影响的紧循环环境中进行大型计算,则应阅读
aValue*8==aValue),使用位运算(被认为比算术运算快)

当它的幂为2个数字(2^x)时,最好使用移位-它只是“推”位。(1次汇编操作,而不是2次除法)


有哪种语言的编译器可以进行这种优化?

位移位是一种“接近金属”的操作,在大多数情况下,它不包含任何关于您真正想要实现什么的信息

如果你想把一个数字除以二,那么一定要写
x/2
。它恰好是通过
x>>1
实现的,但后者隐藏了意图


当这成为瓶颈时,请修改代码。

不同之处在于算术运算有明确定义的结果(除非它们遇到有符号溢出)在许多情况下,移位操作没有定义的结果。它们对于C和C++中的无符号类型都是明确定义的,但是使用带签名的类型的事物很快就变得棘手。 在C++语言中,没有定义左移位<代码> < /符号类型的代码。它只是移位位,在右边填充零点。算术意义上的含义取决于平台所使用的符号表示。对于右移代码> 操作符,实际上是相同的。正确地移位负值。导致实现定义的结果

在C语言中,事物的定义略有不同。左移负值是不可能的:它会导致未定义的行为。右移负值会导致实现定义的结果

在大多数实际实现中,每一个右移执行2除法,并向负无穷大舍入。顺便说一句,这与算术除法
/
2明显不同,因为它通常(并且总是在C99中)的时间将向0舍入


至于什么时候应该使用位移位……位移位用于对位进行操作。位移位运算符很少被用作算术运算符的替代品(例如,您永远不应该使用移位来执行常量乘除).

只要在2er功率范围内进行乘法或除法运算,就可以更快地进行换档操作,因为这是一次操作(只需要一个处理周期)。
人们很快就习惯了阅读>2 as/4,所以我不同意在使用移位时可读性消失,但这取决于每个人

如果你想知道更多关于如何以及为什么这样做的细节,也许维基百科可以帮助你,或者如果你想通过痛苦学习程序集;-)

什么是做手术的“最佳”方式?

处理数字时使用算术运算。处理位时使用位操作。时期这是常识。我怀疑是否有人会认为将位移位操作用于int或double作为日常事务是一个好主意

何时使用位移位更好?

在处理比特时


附加问题:在算术溢出的情况下,它们的行为是否相同?

对。大多数现代编译器(通常,但并非总是)将适当的算术运算简化为相应的位移位运算


编辑:答案被接受,但我只想补充一点,在这个问题中有很多不好的建议。在处理int时,不应该(读:几乎不应该)使用位移位操作。这是一种可怕的做法。

当你的目标是将一些数字相乘时,使用算术运算符是有意义的

当您的目标是实际逻辑移位位时,请使用移位运算符

例如,假设您正在从RGB字中拆分RGB组件,此代码有意义:

int aNumber;

aNumber = aValue / 2;
aNumber = aValue >> 1;

aNumber = aValue * 2;
aNumber = aValue << 1;

aNumber = aValue / 4;
aNumber = aValue >> 2;

aNumber = aValue * 8;
aNumber = aValue << 3;

// etc.

另一方面,当您想将一些值乘以4时,您应该真正编写您的意图,而不是进行转换。

作为区别的示例,这是使用gcc 4.4和-O3创建的x86程序集

 int r,g,b;
 short rgb = 0x74f5;
 b = rgb & 0x001f;
 g = (rgb & 0x07e0) >> 5;
 r = (rgb & 0xf800) >> 11;
int算术0(int aValue)
{
返回值/2;
}
00000000 :
0:55推力%ebp
1:89 e5 mov%esp,%ebp
3:8b 45 08 mov 0x8(%ebp),%eax
6:5d pop%ebp
7:89 c2 mov%eax,%edx
9:c1 ea 1f shr$0x1f,%edx
c:8d 04 02 lea(%edx,%eax,1),%eax
f:d1 f8 sar%eax
11:c3 ret
整数算术1(整数aValue)
{
返回aValue>>1;
}
00000020 :
20:55%推压ebp
21:89 e5 mov%esp,%ebp
23:8b 45 08 mov 0x8(%ebp),%eax
26:5d流行百分比ebp
27:d1 f8 sar%eax
29:c3 ret
整数算术2(整数aValue)
{
返回值*2;
}
00000030 :
30:55推力%ebp
31:89 e5移动百分比esp,%ebp
33:8b 45 08 mov 0x8(%ebp),%eax
36:5d流行百分比ebp
37:01 c0添加%eax,%eax
39:c3 ret
整数算术3(整数aValue)
{
返回值>2;
}
00000070 :
70:55推力%ebp
71:89 e5 mov%esp,%ebp
73:8b 45 08 mov 0x8(%ebp),%eax
76:5d流行百分比ebp
77:c1 f8 02 sar$0x2,%eax
7a:c3
int arithmetic0 ( int aValue )
{
    return aValue / 2;
}

00000000 <arithmetic0>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 08                mov    0x8(%ebp),%eax
   6:   5d                      pop    %ebp
   7:   89 c2                   mov    %eax,%edx
   9:   c1 ea 1f                shr    $0x1f,%edx
   c:   8d 04 02                lea    (%edx,%eax,1),%eax
   f:   d1 f8                   sar    %eax
  11:   c3                      ret    

int arithmetic1 ( int aValue )
{
    return aValue >> 1;
}

00000020 <arithmetic1>:
  20:   55                      push   %ebp
  21:   89 e5                   mov    %esp,%ebp
  23:   8b 45 08                mov    0x8(%ebp),%eax
  26:   5d                      pop    %ebp
  27:   d1 f8                   sar    %eax
  29:   c3                      ret    

int arithmetic2 ( int aValue )
{
    return aValue * 2;
}

00000030 <arithmetic2>:
  30:   55                      push   %ebp
  31:   89 e5                   mov    %esp,%ebp
  33:   8b 45 08                mov    0x8(%ebp),%eax
  36:   5d                      pop    %ebp
  37:   01 c0                   add    %eax,%eax
  39:   c3                      ret    

int arithmetic3 ( int aValue )
{
    return aValue << 1;
}

00000040 <arithmetic3>:
  40:   55                      push   %ebp
  41:   89 e5                   mov    %esp,%ebp
  43:   8b 45 08                mov    0x8(%ebp),%eax
  46:   5d                      pop    %ebp
  47:   01 c0                   add    %eax,%eax
  49:   c3                      ret    

int arithmetic4 ( int aValue )
{
    return aValue / 4;
}

00000050 <arithmetic4>:
  50:   55                      push   %ebp
  51:   89 e5                   mov    %esp,%ebp
  53:   8b 55 08                mov    0x8(%ebp),%edx
  56:   5d                      pop    %ebp
  57:   89 d0                   mov    %edx,%eax
  59:   c1 f8 1f                sar    $0x1f,%eax
  5c:   c1 e8 1e                shr    $0x1e,%eax
  5f:   01 d0                   add    %edx,%eax
  61:   c1 f8 02                sar    $0x2,%eax
  64:   c3                      ret    

int arithmetic5 ( int aValue )
{
    return aValue >> 2;
}

00000070 <arithmetic5>:
  70:   55                      push   %ebp
  71:   89 e5                   mov    %esp,%ebp
  73:   8b 45 08                mov    0x8(%ebp),%eax
  76:   5d                      pop    %ebp
  77:   c1 f8 02                sar    $0x2,%eax
  7a:   c3                      ret    

int arithmetic6 ( int aValue )
{
    return aValue * 8;
}

00000080 <arithmetic6>:
  80:   55                      push   %ebp
  81:   89 e5                   mov    %esp,%ebp
  83:   8b 45 08                mov    0x8(%ebp),%eax
  86:   5d                      pop    %ebp
  87:   c1 e0 03                shl    $0x3,%eax
  8a:   c3                      ret    

int arithmetic7 ( int aValue )
{
    return aValue << 4;
}

00000090 <arithmetic7>:
  90:   55                      push   %ebp
  91:   89 e5                   mov    %esp,%ebp
  93:   8b 45 08                mov    0x8(%ebp),%eax
  96:   5d                      pop    %ebp
  97:   c1 e0 04                shl    $0x4,%eax
  9a:   c3                      ret    
aNumber = aValue * 8;
aNumber = aValue << 4;
int i = -11;
std::cout << (i  / 2) << '\n';   // prints -5 (well defined by the standard)
std::cout << (i >> 1) << '\n';   // prints -6 (may differ on other platform)