Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Byte reversing? 2

Status
Not open for further replies.

fl0ra

MIS
Jul 27, 2004
93
FR
Another quick question:
I want to reverse the byte(not the bit) I already read in one buffer.
I pretty confident there is an existing C function that does that already right?
I can write one but I do not think there is any need reinvinting the wheel, innit?

say for instance I have read four bytes:
64 C0 0C 0E
and I want them to be
0E 0C C0 64


cheers
 
> I want to reverse the byte(not the bit) I already read in one buffer.

You meant inverse byte order in 4-byte word?

> I pretty confident there is an existing C function that does that already right?

Probably not.
 
ok...
well I've made my own then:

Code:
void ReverseBytes(unsigned char * buffer, size_t length) {
  register int i;
  register int j;
  unsigned char buff[length];
  memset(buff,0,(length*sizeof(unsigned char)));
  for(i=0,j=length-1;i<length;i++,j--)
  {
    memmove(&(buff[i]),&(buffer[j]),sizeof(unsigned char));
  }
  memmove(buffer,buff,length);
}


There is probably more efficient way of doing it...
Any bright ideas?
 
Code:
unsigned char temp;
temp = buff[0];
buff[0] = buff[3];
buff[3] = temp;
temp = buff[1];
buff[1] = buff[2];
buff[2] = temp;

--
 
fl0ra said:
I pretty confident there is an existing C function that does that already right?
You may be thinking of [tt]htonl[/tt].
Code:
#include <stdio.h>
#include <winsock2.h>

int main ()
{
   unsigned int value  = 0x64C00C0E;
   unsigned int result = htonl(value);
   printf("value  = 0x%08X\n", value);
   printf("result = 0x%08X\n", result);
   return 0;
}

/* my output
value  = 0x64C00C0E
result = 0x0E0CC064
*/
 
But if your machine happens to be one which stores data in network byte order (ie big-endian), then htonl doesn't actually do anything.

--
 
thx guys...
but are you pretty confident that this function
Code:
void ReverseBytes(unsigned char * buffer, size_t length) {
  register int i;
  register int j;
  unsigned char buff[length];
  memset(buff,0,(length*sizeof(unsigned char)));
  for(i=0,j=length-1;i<length;i++,j--)
  {
    memmove(&(buff[i]),&(buffer[j]),sizeof(unsigned char));
  }
  memmove(buffer,buff,length);
}

is the most efficient I can write?
because your solution Salem is good but I just wanna be able to cope with variable length... not only 4 bytes
 
Change the first memmove to
Code:
buff[i] = buff[j];
You don't need memmove to copy 1 character.
 
ok cool
took that onboard...

any others bright optimisation?
 
Code:
void ReverseBytes(unsigned char *buffer, size_t length)
{
register int i;
register unsigned char *pnt1;
register unsigned char *pnt2;
register unsigned char temp;

   pnt1=buffer;
   pnt2=buffer+length-1;
   for(i=0; i<length/2; i++)
   {
      temp=(*pnt1);
      (*pnt1++)=(*pnt2);
      (*pnt2--)=temp;
   }
}
 
More robust (and universal;) variation:
Code:
void* ReverseBytes(void* buffer, int bsz)
{
  typedef unsigned char Uchar;
  register Uchar* pbuf = (Uchar*)buffer; /* cast for C++ */
  register Uchar* pend, wchar; /* register as decoration */
  if (pbuf && bsz > 1)
  {
     pend = pbuf + bsz;
     bsz >>= 1;
     while (bsz--)
     {
       wchar = *pbuf;
       *pbuf++ = *--pend;
       *pend = wchar;
     }
  }
  return buffer;
}
 

>> any others bright optimisation?

maybe:

Code:
void * ReverseBytes(void * buffer, size_t length) {
 register unsigned char temp, * p, * e;
 if(length) {
  for(p = buffer, e = p + (length - 1); p != e; ++p, e--) {
   temp = *p;
   *p = *e;
   *e = temp;
   }
  }
 return buffer;
 }
 
Code:
for(p = buffer, e = p + (length - 1); p [red][b]!=[/b][/red] e; ++p, e--) {
I think you'd be much better off with this.
Code:
for(p = buffer, e = p + (length - 1); p [blue][b]<[/b][/blue] e; ++p, e--) {
 


either way works fine since the end pointer is guaranteed to be greater or equal to the forward iterator (since length is unsigned).
 
of course, using your method we don't have to test length's non-zero-ness at the beginning of the loop...so I suppose you're right. =)
 
smgarth said:
either way works fine since the end pointer is guaranteed to be greater or equal to the forward iterator (since length is unsigned).
Have you tried it with both even- and odd-sized arrays?
 

well, if it's even-sized the two center bytes are swapped; if it's odd-sized the center byte remains the same (as it should).
 
This is what I was getting at in regard to the even- and odd-sized arrays: using != instead of < may result in an infinite loop.
Code:
#include <stdio.h>

void display ( const void *buffer, size_t size )
{
   const unsigned char *byte = buffer;
   while ( size-- )
   {
      printf ( "%X ", *byte++ );
   }
   putchar ( '\n' );
}

void *reverse ( void *buffer, size_t size )
{
   unsigned char *start, *end;
#ifndef NDEBUG
   printf("reverse: size = %lu\n", (long unsigned)size);
#endif
   for ( start = buffer, end = start + (size - 1); start < end; ++start, --end )
   {
      unsigned char swap = *start;
      *start = *end;
      *end = swap;
#ifndef NDEBUG
      printf("start = %p, end = %p\n", (void*)start, (void*)end);
#endif
   }
   return buffer;
}

void * ReverseBytes(void * buffer, size_t length)
{
   register unsigned char temp, * p, * e;
#ifndef NDEBUG
   printf("ReverseBytes: size = %lu\n", (long unsigned)length);
#endif
   if ( length )
   {
      for ( p = buffer, e = p + (length - 1); p != e; ++p, e-- )
      {
         temp = *p;
         *p = *e;
         *e = temp;
#ifndef NDEBUG
         printf("p = %p, e = %p\n", (void*)p, (void*)e);
         if ( e < buffer )
         {
            puts("do you see the issue yet?\nwhat if this were not here?");
            break;
         }
#endif
      }
   }
   return buffer;
}

int main ( void )
{
   unsigned char odd[] = {0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE};
   unsigned char even[] = {0x12,0x34,0x56,0x78,0x9A,0xBC};

   puts("odd:");
   display ( odd, sizeof odd );
   display ( reverse ( odd, sizeof odd ), sizeof odd );
   display ( ReverseBytes ( odd, sizeof odd ), sizeof odd );

   puts("\neven:");
   display ( even, sizeof even );
   display ( reverse ( even, sizeof even ), sizeof even );
   display ( ReverseBytes ( even, sizeof even ), sizeof even );

   return 0;
}

/* my output
odd:
12 34 56 78 9A BC DE 
reverse: size = 7
start = 0012FF84, end = 0012FF8A
start = 0012FF85, end = 0012FF89
start = 0012FF86, end = 0012FF88
DE BC 9A 78 56 34 12 
ReverseBytes: size = 7
p = 0012FF84, e = 0012FF8A
p = 0012FF85, e = 0012FF89
p = 0012FF86, e = 0012FF88
12 34 56 78 9A BC DE 

even:
12 34 56 78 9A BC 
reverse: size = 6
start = 0012FF7C, end = 0012FF81
start = 0012FF7D, end = 0012FF80
start = 0012FF7E, end = 0012FF7F
BC 9A 78 56 34 12 
ReverseBytes: size = 6
p = 0012FF7C, e = 0012FF81
p = 0012FF7D, e = 0012FF80
p = 0012FF7E, e = 0012FF7F
p = 0012FF7F, e = 0012FF7E
p = 0012FF80, e = 0012FF7D
p = 0012FF81, e = 0012FF7C
p = 0012FF82, e = 0012FF7B
do you see the issue yet?
what if this were not here?
BC 9A 78 56 34 12 
*/
 

of course! I completely overlooked that - touche! good job, Dave. I think I've been spending too much time with the stl this week...must...take...break.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top