tags:

views:

862

answers:

9

I was doing some basic audio programming in C# using the NAudio package and I came across the following expression and I have no idea what it means, as i've never seen the << operator being used before. So what does << mean?

Please give a quick explaination of this expression.

short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]);
+4  A: 

It's called left-shift operator.

Follow this link for more detailed information.

missingfaktor
+8  A: 

Shift left (and the counterpart, Shift right) moves the bits in the given direction.

Shift left is more or less times 2, but faster

Shift right is more or less divided by 2, but faster

Benjamin Podszun
You can safely leave out the comparison to multiplying or dividing by two. This just gets us another bunch of programmers who think they can out-smart the compiler by writing `x << 1` instead of `x * 2`. No −1 from me, but close.
Joey
But it is probably the reason why it was used in his audio code. So - my hope is to help him to understand not only what it does, but also the probable intention.
Benjamin Podszun
If the intention was arithmetic, i. e. × 2, then I think it's a very bad idea to use bit shifts. If the intention was bitwise, i. e. “move those bits around a bit”, then of course it's the right idiom. Remember that it has to make sense to someone reading the code. The compiler is almost always better at figuring out how to write it properly that it performs as fast as possible. (And seeing the code it very obviously is a *bitwise* context, not an arithmetic one—it combines two bytes into one word).
Joey
@Benjamin: The "but faster" claims are misleading. I'm pretty sure that the compiler and/or JITter recognises integer `*2` and `/2` calculations and uses a shift instruction anyway where possible, so in C# there is no performance benefit.
LukeH
+1 to Luke. Something like `x * 2` might even be rewritten to `x + x` in some cases :-)
Joey
@Johannes: I don't know more about the context, but audio/video and limited/embedded devices (we can argue if C# is relevant there..) might call for integer math@Luke: Good pointI see both of your points. Suggestions how I can soften it up?
Benjamin Podszun
+1  A: 

Left shift Here is some msdn to help you : http://msdn.microsoft.com/en-us/library/ayt2kcfb(VS.80).aspx

JonH
+6  A: 

It's a left bit shift operation, a VERY common programming idiom: http://en.wikipedia.org/wiki/Arithmetic_shift

mletterle
Its not common in C#...
Kragen
It is if you're playing the part of a bit flipper :) Alot of people doing C# aren't "plumbers" though so they don't see all that niftyness.
mletterle
@Kragen, IMHO, is not common not only in C# but also in other programming languages. Evidently, if you perform complex binary or logical bit operations this will be a common for you...
serhio
@serhio - Is that an intentional double negative? Makes it difficult to get your point. Are you agreeing with Kragen? Seems like you are but then you last sentence suggests you arn't.
runrunraygun
@runrunraygun: Yes, I not only agree with Kragen, but also extend his affirmation to the programming world in general. In the past, when working more with binary numbers that should be a common (maybe even VERY common) operator. Not now, in the OOP era... if you get the point..
serhio
+48  A: 

Definition

The left-shift operator (<<) shifts its first operand left by the number of bits specified by its second operand. The type of the second operand must be an int. << Operator (MSDN C# Reference) alt text

For binary numbers it is a bitwise operation that shifts all of the bits of its operand; every bit in the operand is simply moved a given number of bit positions, and the vacant bit-positions are filled in.

Usage

Arithmetic shifts can be useful as efficient ways of performing multiplication or division of signed integers by powers of two. Shifting left by n bits on a signed or unsigned binary number has the effect of multiplying it by 2n. Shifting right by n bits on a two's complement signed binary number has the effect of dividing it by 2n, but it always rounds down (towards negative infinity). This is different from the way rounding is usually done in signed integer division (which rounds towards 0). This discrepancy has led to bugs in more than one compiler.

An other usage is work with color bits. Charles Petzold Foundations article "Bitmaps And Pixel Bits" shows an example of << when working with colors:

ushort pixel = (ushort)(green << 5 | blue);
serhio
+1 .. I love pictures !
Stan R.
I've updated this answer because shifting multiplies/divides by 2^n, not 2n
John Rasch
@John: Yeah. Thanks for formatting, John.
serhio
+1  A: 

As a few people have pointed out already it is a shift operation.

However It is worth noting that depending on whether the operand is a signed integral type or a unsigned integral type it will apply either an arithmetic or logical shift.

See the bottom of this page on msdn.

runrunraygun
+1  A: 

The "<<" is a shift left operator. x << y shifts bit pattern x *y* position left.

For example, if x was 0001 0101 and y was 1 then the result would be 0010 1010. It's like someone's pushed each bit left one.

_wdh
+1  A: 

As others have said the << operator moves the bits of a number left. The normal reason why someone would do this in an Audio application is to combine two 8bit mono-samples (one for left and right) into a 16 bit sterio sample.

So in the sample code it looks like Buffer contains sterio encoded with left and right in alternate samples. By shifting the first left 8 and oring the second the author is combining them to form a 16bit sterio sample with the High 8bits being one channel and the low 8bits being the other.

If in your example the buffer contained:

1001 0100 (Right)
1001 0011 (Left)

The result you would get in sample is:

(Left)    (Right)
1001 0011 1001 0100
Martin Brown
+1  A: 

The bitwise operator has already been explained quite a few times already. Let's say that buffer[0] contains 1, buffer[1] contains 2 and index is 0 and replace these values:

short sample = (short)((buffer[1] << 8) | buffer[0]);
short sample = (short)((1 << 8) | 2);

Now, a semi-graphical representation. This is the numeral 1 in a binary representation:

0000 0001

Shifting eight positions to the left would make this number to "overflow" from a single byte. However, the compiler is smart enough to give us more room.

0000 0001 0000 0000

Now, the right part: the number 2 looks like this in binary:

0000 0010

And the "|" operator (bitwise OR) makes just put the two values together and comparing bit per bit.

  0000 0001 0000 0000
| 0000 0000 0000 0010
= 0000 0001 0000 0010

And the final value is stored in your "sample" variable (in this case, 258.) The reverse operation is similar:

buffer[0] = sample & 255;
buffer[1] = (sample & (255 << 8)) >> 8;
Leonardo Herrera