How to swap bytes in variables (VS2005)???

B

Bo Berglund

Preamble:
I am a Delphi (Pascal) programmer who has stumbled into the C++ world
by necessity since Borland has no 64 bit compiler yet out....
I used to do a lot of ANSI C programming for embedded systems about 15
years or so back, but since I started to do Windows programs I have
been using VB at first and then Delphi.

Problem:
When I communicate with embedded systems quite often the data are read
as binary streams and I have to compensate for the backwords storage
problem (Intel vs Motorola).
So in Delphi I have used the built-in Swap() function for reversing
the bytes in a 2-byte variable like an "unsigned short int" or "word"
in Pascal. I also have built a Swap32 function to handle 4-byte swaps.
Now I need to get this to work in C++ and I am getting errors all over
the place. Help appreciated.
Here is my code:

1. I have declared two struct type as follows:

typedef struct mytag16 {
unsigned char C1;
unsigned char C2;
}Reverse16;

typedef struct mytag32 {
unsigned char C1;
unsigned char C2;
unsigned char C3;
unsigned char C4;
}Reverse32;

It took a while to realize that the ANSI C declaration is different
(the name of the type goes before the braces and nothing comes after).

2. I am using these types in two functions to reverse the byte orders:

unsigned short Swap(unsigned short Source)
// Swap high and low chars of 16 bit word value
{
Reverse16 Tmp, Tmp2;
unsigned short Result;

Tmp = (Reverse16)Source;
Tmp2 = Tmp;
Tmp.C1 = Tmp.C2;
Tmp.C2 = Tmp2.C1;
Result = (unsigned short)Tmp;
return (Result);
}

and

void Swap32(*Source, bool bFlip)
// Swap high and low word of 32 bit source. If bFlip also swap whole
words
{
Reverse32 Tmp, Tmp2;

Tmp = (Reverse32)Source;
Tmp2 = Tmp;
if (bFlip)
{
Tmp.C1 = Tmp.C4;
Tmp.C2 = Tmp.C3;
Tmp.C3 = Tmp2.C2;
Tmp.C4 = Tmp2.C1;
}
else
{
Tmp.C1 = Tmp.C2;
Tmp.C2 = Tmp2.C1;
Tmp.C3 = Tmp.C4;
Tmp.C4 = Tmp2.C3;
}
Source = Tmp;
}

When i build the project I get a lot of errors like this:

1>..\..\..\Tests\AGI\TestAGI.cpp(82) : error C2440: 'type cast' :
cannot convert from 'unsigned short' to 'Reverse16'
1> No constructor could take the source type, or constructor
overload resolution was ambiguous

1>..\..\..\SentinelTests\AGI\SentinelAGI.cpp(83) : error C2440: 'type
cast' : cannot convert from 'unsigned short' to 'Reverse16'
1> No constructor could take the source type, or constructor
overload resolution was ambiguous

Apparently my typecast is not working, but why???
The structs are 2- and 4-bytes and the variables I am casting are also
2- and 4-bytes, so why does it not work?

And is there some built-in function I can use in place of my own to
reverse the byte orders?

/Bo


Bo Berglund
bo.berglund(at)nospam.telia.com
 
D

David Lowndes

When i build the project I get a lot of errors like this:
1>..\..\..\Tests\AGI\TestAGI.cpp(82) : error C2440: 'type cast' :
cannot convert from 'unsigned short' to 'Reverse16'
...
Apparently my typecast is not working, but why?
The structs are 2- and 4-bytes and the variables I am casting are also
2- and 4-bytes, so why does it not work?

You have to be a bit more devious - use pointers to the variables,
cast the pointers to pointers to the desired types, then dereference
the pointers. In C++ it's also safest to use the newer casts too -
static_cast<>().

Alternatively, use a union.
And is there some built-in function I can use in place of my own to
reverse the byte orders?

Have you seen the _swab() function?

Dave
 
N

Nathan Mates

So in Delphi I have used the built-in Swap() function for reversing
the bytes in a 2-byte variable like an "unsigned short int" or
"word" in Pascal. I also have built a Swap32 function to handle
4-byte swaps. Now I need to get this to work in C++ and I am
getting errors all over the place. Help appreciated.

You used a bunch of structs, which is a bit of overkill. C/C++ give
you access to bitshift operators, which allow you to directly pick and
move bits around. Your functions can be rewritten as:

unsigned short Swap16(unsigned short v)
{
return ((v & 0xFF) << 8) |
((v >> 8) & 0xFF);
}


unsigned long Swap32(unsigned long v)
{
return ((v & 0xFF) << 24) |
(((v >> 8) & 0xFF) << 16) |
(((v >> 16) & 0xFF) << 8) |
(((v >> 24) & 0xFF);
}

Nathan Mates
 
N

Nathan Mates

unsigned short Swap16(unsigned short v)
{
return ((v & 0xFF) << 8) |
((v >> 8) & 0xFF);
}

Hm. I shouldn't post before I'm fully awake. The functions I posted
can be slightly optimized and/or clarified a bit better.

unsigned short Swap16(unsigned short v)
{
return ((v & 0x00FF) << 8) |
((v & 0xFF00) >> 8);
}


unsigned long Swap32(unsigned long v)
{
return ((v & 0x000000FF) << 24) |
((v & 0x0000FF00) << 8) |
((v & 0x00FF0000) >> 8) |
((v & 0xFF000000) >> 24);
}

Nathan Mates
 
B

Bo Berglund

Hm. I shouldn't post before I'm fully awake. The functions I posted
can be slightly optimized and/or clarified a bit better.

unsigned short Swap16(unsigned short v)
{
return ((v & 0x00FF) << 8) |
((v & 0xFF00) >> 8);
}


unsigned long Swap32(unsigned long v)
{
return ((v & 0x000000FF) << 24) |
((v & 0x0000FF00) << 8) |
((v & 0x00FF0000) >> 8) |
((v & 0xFF000000) >> 24);
}

Nathan Mates

Thanks!
That brought down my error count from 36 to 22...

Bo Berglund
bo.berglund(at)nospam.telia.com
 
B

Ben Voigt

If you know your data is in network byte order, then use htons and htonl
functions. They will do the byte swapping on Intel, but if you ever
compiled your code on an ARM or Alpha or whatever, they'll still do the
right thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top