运算符“<<”在 C# 中是啥意思?
Posted
技术标签:
【中文标题】运算符“<<”在 C# 中是啥意思?【英文标题】:What does the operator "<<" mean in C#?运算符“<<”在 C# 中是什么意思? 【发布时间】:2011-01-01 17:26:30 【问题描述】:我正在使用 NAudio 包在 C# 中进行一些基本的音频编程,我遇到了以下表达式,但我不知道它是什么意思,因为我以前从未见过
请快速解释一下这个表达式。
short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]);
【问题讨论】:
+1 撤消反对票。我认为这是一个很好的问题 我没有反对,但它让我觉得这是一个 RTFD 问题。 serhio:用谷歌搜索“ @Johannes:但是你可以直接在VS文档的索引中输入。 只要还没有在 SO 上被问到,最好放在这里 【参考方案1】:定义
左移运算符 (<< Operator (MSDN C# Reference)
对于二进制数,它是一种移位操作数的所有位的按位运算;操作数中的每个位都简单地移动给定数量的位位置,然后填充空位。
用法
算术移位可用作执行有符号整数乘以或除以 2 的幂的有效方法。在有符号或无符号二进制数上左移 n 位具有将其乘以 2n 的效果。将二进制补码符号二进制数右移 n 位的效果是将其除以 2n,但它总是向下舍入(朝向负无穷大)。这不同于通常在有符号整数除法中进行舍入的方式(向 0 舍入)。这种差异导致多个编译器出现错误。
另一种用法是使用颜色位。 Charles Petzold Foundations article "Bitmaps And Pixel Bits" 展示了
ushort pixel = (ushort)(green << 5 | blue);
【讨论】:
我已经更新了这个答案,因为移位乘以/除以 2^n,而不是 2n 请注意,虽然只有一种类型的左移,但有两种类型的右移。 “算术移位”符号扩展,而“逻辑移位”零扩展。 C# 根据操作数的类型做正确的事。另一方面,C 对正数做了正确的事情,但将包含负数的有符号类型的处理保留为“实现定义”。【参考方案2】:左移(和对应的右移)在给定方向移动位。
左移或多或少是 2 的倍数,但更快
右移或多或少除以 2,但更快
【讨论】:
您可以放心地忽略比较乘以或除以二。这让我们又多了一群程序员,他们认为他们可以通过编写x << 1
而不是x * 2
来超越编译器。我没有-1,但很接近。
但这可能是他的音频代码中使用它的原因。所以 - 我的希望是帮助他不仅了解它的作用,而且了解可能的意图。
如果意图是算术,i。 e. × 2,那么我认为使用位移是一个非常糟糕的主意。如果意图是按位的,我。 e. “将这些位移动一点”,那当然是正确的成语。请记住,它必须对阅读代码的人有意义。编译器几乎总是更善于弄清楚如何正确编写它以尽可能快地执行。 (看到代码,很明显它是一个 bitwise 上下文,而不是算术上下文——它将两个字节组合成一个单词)。
@Benjamin:“但更快”的说法具有误导性。我很确定编译器和/或 JITter 可以识别整数 *2
和 /2
计算并尽可能使用移位指令,因此在 C# 中没有性能优势。
+1 给卢克。在某些情况下,像x * 2
这样的东西甚至可能被重写为x + x
:-)【参考方案3】:
这是一个左移操作,一个非常常见的编程习惯:http://en.wikipedia.org/wiki/Arithmetic_shift
【讨论】:
如果你在扮演一个有点蹩脚的角色 :) 很多做 C# 的人不是“水管工”,所以他们看不到所有的漂亮。 @Kragen,恕我直言,不仅在 C# 中而且在其他编程语言中并不常见。显然,如果您执行复杂的二进制或逻辑位操作,这对您来说很常见...... @serhio - 这是故意的双重否定吗?让你很难理解你的观点。你同意克拉根的观点吗?好像你是,但你最后一句话暗示你不是。 @runrunraygun:是的,我不仅同意 Kragen 的观点,而且还将他的肯定扩展到整个编程世界。过去,当更多地使用二进制数时,这应该是一个常见的(甚至可能是非常常见的)运算符。不是现在,在 OOP 时代......如果你明白了......【参考方案4】:称为左移运算符。
关注this链接了解更多详细信息。
【讨论】:
【参考方案5】:位运算符已经解释了好几次了。假设 buffer[0]
包含 1,buffer[1]
包含 2 并且 index
为 0 并替换这些值:
short sample = (short)((buffer[1] << 8) | buffer[0]);
short sample = (short)((1 << 8) | 2);
现在,一个半图形表示。这是二进制表示中的数字 1:
0000 0001
向左移动八个位置会使这个数字从单个字节“溢出”。但是,编译器足够聪明,可以给我们更多空间。
0000 0001 0000 0000
现在,右边的部分:数字 2 在二进制中看起来像这样:
0000 0010
还有“|”运算符(按位或)只需将两个值放在一起并逐位比较。
0000 0001 0000 0000
| 0000 0000 0000 0010
= 0000 0001 0000 0010
最终值存储在您的“样本”变量中(在本例中为 258。)反向操作类似:
buffer[0] = sample & 255;
buffer[1] = (sample & (255 << 8)) >> 8;
【讨论】:
【参考方案6】:左移 这里有一些 msdn 可以帮助你:http://msdn.microsoft.com/en-us/library/ayt2kcfb(VS.80).aspx
【讨论】:
【参考方案7】:“x y 将位模式 x y 位置向左移动。
例如,如果 x 是 0001 0101 并且 y 是 1,那么结果将是 0010 1010 .就好像有人往左推一样。
【讨论】:
【参考方案8】:正如一些人已经指出的那样,这是一个移位操作。
然而值得注意的是,根据操作数是有符号整数类型还是无符号整数类型,它将应用算术或逻辑移位。
查看本页底部on msdn.
【讨论】:
【参考方案9】:正如其他人所说,
因此,在示例代码中,Buffer 包含在交替样本中使用左右编码的 sterio。作者通过将第一个左移 8 和第二个 oring 组合起来形成一个 16 位立体声样本,其中高 8 位是一个通道,低 8 位是另一个。
如果在您的示例中缓冲区包含:
1001 0100 (Right)
1001 0011 (Left)
你会在样本中得到的结果是:
(Left) (Right)
1001 0011 1001 0100
【讨论】:
以上是关于运算符“<<”在 C# 中是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章