views:

235

answers:

3

Does not work as expected becuase it does not set the MSB bit correct. I am using metrowerks compiler.

//shifting right 5 characters
char * buffer;
buffer=global_buffer;
for(i=0;i<5;i++) //shift right for 1;
{
    buffer[17-i]=(buffer[17-i]>>1)|(buffer[17-i-1]<<7);
}

EDIT input buffer (just before for loop) 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x2F,0xA0,0xC6,0x9D

i got after for loop 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x17,0xD0,0xE3,0xCE

+9  A: 

You probably want "unsigned char *buffer;" This will shift zeros into the top bits rather than retaining the sign bit.

Richard Pennington
Right shifting a signed value does not always retain the sign bit. See Steve Jessops Answer. Also see some of the discussion with the question: http://stackoverflow.com/questions/1857928/right-shifting-negative-numbers-in-c
Trent
@Trent: I didn't tell him to right shift a signed value. I told him to right shift an unsigned value.
Richard Pennington
@Trent: In fact, as your link says, even signed shifts usually work as expected. I'm not aware of an architecture (in current use) that they don't.
Richard Pennington
Trent gave an example in a comment to an answer on that question which makes the same incorrect claim: "The Microchip C18 compiler (a link to the user guide can be found here: http://tinyurl.com/ybt2svs - see section B.4)". I'm not aware of a CPU that has "signed" and "unsigned" registers, so note that it's down to the compiler what shift is used for signed integer types. The architecture has nothing to do with it. Unless it doesn't have an arithmetic shift at all, in which case it constrains what compilers can do efficiently on that architecture.
Steve Jessop
@Richard, I know you told him to shift a unsigned value, but you also incorrectly implied that right shifting a signed value retains the sign bit.
Trent
@Trent, His compiler does retain the sign bit.
Richard Pennington
+2  A: 

"it does not set the MSB bit correct".

The C standard says:

6.5.7/5 ... If E1 has a signed type and a negative value, the resulting value is implementation-defined.

See this draft, for example: http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf

Presumably char is signed on your compiler, so you should check your compiler docs to see what is the correct value of the MSB. And all the other bits.

Steve Jessop
A: 

Just thinking out loud:
Objective: shift an array of bytes right by one bit.

Process: Perform a logical shift right with carry the same way a processor would.

unsigned char carry = 0; // Initial value to shift in as MSB.
for (unsigned int i = 0; i < 5; ++i)
{
  // Save carry to next octet.
  unsigned int new_carry = buffer[17 - i] & 1;

  // Right shift the current octet.
  buffer[17 - i] >>= 1;

  // "Shift in" previous carry.
  buffer[17 - i] = buffer[17 - i] | (carry << 7);

  // Propagate the next carry.
  carry = new_carry;
}

This code is not optimized nor tested.

Thomas Matthews