tags:

views:

494

answers:

7

I have some problems with this syntax. Could somebody explain to me what this C function is doing?

unsigned long protodec_henten(int from, int size, unsigned char *frame)
{
   int i = 0;
   unsigned long tmp = 0;

   for (i = 0; i < size; i++)
     tmp |= (frame[from + i]) << (size - 1 - i);

   return tmp;
}

Thank you!

A: 

Looks like a hashing function. On second thought this would make a pretty poor hash function.

They are shifting every frame by the remainder of the size and then ORing that with a static value. This value is then returned.

toast
Just realized that it would be a crappy hashing function since eventually the value would get to 1111 1111.
toast
Yeah, xor (^) is what you'd want for a hash function, not or (|).
David Thornley
A: 

I guess you don't understand the tmp |= because this is probably the only part in the code that is "Hard" to understand. If you try search for C operators you will find a list here, now |= means "Bitwise or", you can read more about them here.

So what this code really does is that it takes some input, you tell the functon where to start reading in the "buffer"/"frame" and you do bitwise or on as many positions as the "size" parameter says.

Filip Ekberg
| is bitwise OR, |= is bitwise OR assignment operator.
Samuel
Yes well do i need to explain that = always assigns?
Filip Ekberg
+15  A: 

I'm guessing you're referring to the following line as the one with the confusing syntax.

tmp |= (frame[from + i]) << (size - 1 - i);

Lets break this down

  • frame[from+i]: "from" represents an initial index into the array and i is simply the current offset. So this is effectively iterating the array starting at index "from"
  • size - 1 - i: This is calculating the number of bits to shift by and is doing so based on the current index. This number will start at size -1 and will decrease as the loop progresses
  • (frame[from+i] << (size - 1 - i): This shifts the value at from+i by the specified number of bits
  • tpm |= ... : Dos a bitwise Or expression on the bytes that are still available once the iterated value has been shifted.
JaredPar
+1 you're the only one that explained in detail probably what he wanted
TStamper
Isn't it shifting by the specified number of bits, not bytes?
Jeff Yates
@Jeff, yes bits not bytes (corrected the typo)
JaredPar
Thank you very much!
Lennart
+7  A: 

Others already described each line, so I'll just add what the function does. You can imagine bytes in frame between positions (from) and (from+size) on a "stack" with different position. First byte will be placed on the left.

bits from:      tmp: |    +  +     |(LSB-side of tmp)
frame[from]:           ---+----
frame[from+1]:          -----+--
frame[from+2]:           -+------
...

Now tmp has a bit set if any of the bytes "below" has a bit set in the related position.

viraptor
A: 

Due to the bitwise OR, this function makes sense only if all values in frame are 0 or 1.

In this case, it will put size consecutive values (i.e. bits) of frame starting at index from into a single unsigned long. The last bit (at index from+size-1) will be inserted as least significant bit.

Eric Bainville
A: 

This overall code is just copying a range of data into the tmp variable. In fact, it is simply doing a memcpy the hard way.

Why not just do: memcpy(&tmp, frame+from, size)

Tim Rupe
Nevermind. It is shifting bits, and not bytes.
Tim Rupe
+2  A: 

Looks like a bit-packer. If, as Eric suggested, all chars in frame are either zero or one, then this will take size characters and pack their values into tmp. For example, if frame (at offset start) contains the values 00 01 00 00 01 01 01 00, then protodec_henten(0,8,frame) would return (leading zeroes omitted) 0x4E (or 01001110 in binary). There are better ways to do this, so it may be doing something else, but it's hard to tell what.

TMN