Valhalla Legends Forums Archive | General Programming | Okay, so I'm not so good at C as I thought..

AuthorMessageTime
tA-Kane
I'm trying to create a C function to do a byteswap (change endianness) of an integer...

But my compiler keeps giving me errors, or, when it doesn't give errors, the results of the test aren't as expected...

Here's the code which I *think* should work, but (perhaps painfully obviously) does not.

Could you tell me what I'm doing wrong? (I don't want the fix, I'd like to get that myself, if I could.)
[CODE]
unsigned long ByteSwap(unsigned long Value){
char *Buffer, *Temp;
unsigned long* rVal;
rVal[0] = Value;
Temp = (char*)rVal[0];
Buffer[0] = Temp[3];
Buffer[1] = Temp[2];
Buffer[2] = Temp[1];
Buffer[3] = Temp[0];
rVal = (unsigned long*)Buffer;
return rVal[0];
}

int main(void){
 unsigned long a, b;
 a = 0x1246578lu
 b = ByteSwap(a);
 printf("%x %x",a,b);
 return 0;
}
[/CODE]

(I'm trying to get the printf to display 12345678 and then 78563412.)
February 15, 2003, 2:06 AM
Zonker
only a couple mistakes in ByteSwap:
[code]unsigned long ByteSwap(unsigned long Value) {
     char Buffer[4], *Temp;
     unsigned long* rVal;
     rVal = &Value;
     Temp = (char*)rVal;
     Buffer[0] = Temp[3];
     Buffer[1] = Temp[2];
     Buffer[2] = Temp[1];
     Buffer[3] = Temp[0];
     rVal = (unsigned long*)Buffer;
     return (unsigned long )*rVal;
} [/code]
You tried to assign values to the Buffer pointer when it hadn't been initialized to anything, so just made it an array.  rVal wasn't initialized either, so i just set it to the address of Value.  That should work perfectly (If you fix the value of a in main ;))

I was bored and wrote a similiar function in asm that is about 9 times faster on my machine if you want it (not the best code, i'm a bit rusty :():
[code]unsigned long MySwap(unsigned long *Value) {
     __asm {
           mov edi, Value                  
           mov ax, word ptr [edi]
           mov bh, al
           mov bl, ah
           mov ax, word ptr [edi+2]
           mov edx, 0
           mov dh, al
           mov dl, ah
           mov ax, bx
           mov cx, 0x08
           shl eax, cl
           shl eax, cl
           mov ax, dx
     }
}[/code]
February 15, 2003, 3:07 AM
Skywing
[quote]only a couple mistakes in ByteSwap:
[code]unsigned long ByteSwap(unsigned long Value) {
     char Buffer[4], *Temp;
     unsigned long* rVal;
     rVal = &Value;
     Temp = (char*)rVal;
     Buffer[0] = Temp[3];
     Buffer[1] = Temp[2];
     Buffer[2] = Temp[1];
     Buffer[3] = Temp[0];
     rVal = (unsigned long*)Buffer;
     return (unsigned long )*rVal;
} [/code]
You tried to assign values to the Buffer pointer when it hadn't been initialized to anything, so just made it an array.  rVal wasn't initialized either, so i just set it to the address of Value.  That should work perfectly (If you fix the value of a in main ;))

I was bored and wrote a similiar function in asm that is about 9 times faster on my machine if you want it (not the best code, i'm a bit rusty :():
[code]unsigned long MySwap(unsigned long *Value) {
     __asm {
           mov edi, Value                  
           mov ax, word ptr [edi]
           mov bh, al
           mov bl, ah
           mov ax, word ptr [edi+2]
           mov edx, 0
           mov dh, al
           mov dl, ah
           mov ax, bx
           mov cx, 0x08
           shl eax, cl
           shl eax, cl
           mov ax, dx
     }
}[/code][/quote]
There's absolutely no need for all of that.
[code]
__asm {
   bswap
}
[/code]
February 15, 2003, 12:28 PM
iago
Nice ruining all the fun! :-)
February 15, 2003, 12:33 PM
Yoni
[quote]
There's absolutely no need for all of that.
[code]
__asm {
   bswap
}
[/code][/quote]
But that's 486+ only!
February 15, 2003, 1:29 PM
tA-Kane
[quote][code]unsigned long ByteSwap(unsigned long Value) {
     char Buffer[4], *Temp;
     unsigned long* rVal;
     rVal = &Value;
     Temp = (char*)rVal;
     Buffer[0] = Temp[3];
     Buffer[1] = Temp[2];
     Buffer[2] = Temp[1];
     Buffer[3] = Temp[0];
     rVal = (unsigned long*)Buffer;
     return (unsigned long )*rVal;
} [/code][/quote]

If rVal was declared as unsigned long (instead of unsigned long*), why doesn't this work:
[CODE]  Temp = (char*)&Value;
 //do byteswap
 rVal = (unsigned long)Buffer;
 return rVal;
[/CODE]
?

Instead of getting the byteswapped value, I get a different value, which I *think* is the address of Value (perhaps the address after a byteswap).
February 15, 2003, 2:45 PM
St0rm.iD
Skywing you loser, he programs on PowerPC.
February 15, 2003, 4:34 PM
Ickypoopy
Why not just
[code]printf("%c%c%c%c", Buffer[3], Buffer[2], Buffer[1], Buffer[0]);[/code]
or
[code]wsprintf(Temp, "%c%c%c%c", Buffer[3], Buffer[2], Buffer[1], Buffer[0]);[/code]
instead of going thru all that trouble?
February 15, 2003, 6:08 PM
tA-Kane
I don't particularly like using printf (or any variant thereof) for something like that...

IMO, printf should be used for something user-readable.

I have nothing else nice to say about printf for a byteswap.
February 15, 2003, 7:06 PM
Skywing
[quote]Skywing you loser, he programs on PowerPC.[/quote]
I was replying to Zonker's unnecessarily complicated function.

There are lots of ways you could swap the bytes of something - I'd recommend either directly using bitwise operations to do it, or defining something like so:

[code]
union {
   DWORD Bits;
   struct {
         BYTE B0;
         BYTE B1;
         BYTE B2;
         BYTE B3;
   };
};
[/code]

You could easily swap the bytes of something by manipulating the members of the structure, which seems to be what you were aiming to do with your function.

Anyways, if you're still having trouble, these are some functions (not particularly great; they'd be better as macros IMO, and they use addition instead of bitwise-OR (?!) but...) which might help, from the VC7 CRT source code:

[code]/***
*rotl.c - rotate an unsigned integer left
*
*       Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _byteswap() - performs a byteswap on an unsigned integer.
*
*******************************************************************************/

#include <cruntime.h>
#include <stdlib.h>

#ifdef _MSC_VER
#pragma function(_byteswap_ulong, _byteswap_uint64, _byteswap_ushort)
#endif  /* _MSC_VER */

/***
*unsigned long _byteswap_ulong(i) - long byteswap
*
*Purpose:
*       Performs a byte swap on an unsigned integer.
*
*Entry:
*       unsigned long i:        value to swap
*
*Exit:
*       returns swaped
*
*Exceptions:
*       None.
*
*******************************************************************************/


unsigned long __cdecl _byteswap_ulong(unsigned long i)
{
   unsigned int j;
   j =  (i << 24);
   j += (i <<  8) & 0x00FF0000;
   j += (i >>  8) & 0x0000FF00;
   j += (i >> 24);
   return j;
}

unsigned short __cdecl _byteswap_ushort(unsigned short i)
{
   unsigned short j;
   j =  (i << 8) ;
   j += (i >> 8) ;
   return j;
}

unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 i)
{
   unsigned __int64 j;
   j =  (i << 56);
   j += (i << 40)&0x00FF000000000000;
   j += (i << 24)&0x0000FF0000000000;
   j += (i <<  8)&0x000000FF00000000;
   j += (i >>  8)&0x00000000FF000000;
   j += (i >> 24)&0x0000000000FF0000;
   j += (i >> 40)&0x000000000000FF00;
   j += (i >> 56);
   return j;

}
[/code]
February 16, 2003, 7:28 PM
St0rm.iD
[quote]
I was replying to Zonker's unnecessarily complicated function.
[/quote]

A likely story.
February 16, 2003, 9:38 PM

Search