From: Giulio Guarnone on
Hi to all,

I've written down this function for perfoming endian conversion :

template<typename T>
T swap_endian(const T& source)
{
T ret = 0;

for (int i = 0; i < sizeof(T); ++i)
{
*(reinterpret_cast<char*>(&ret) + i) =
*(reinterpret_cast<char*>(&source) + sizeof(T) - i - 1);
}
return ret;
}

It seems to work the most of the times, but I'm not sure when I use it
on signed types (int long etc etc) with negative numbers or with
positive numbers like 1520 :

bigendian 0x05F0
littleendian 0xF005

Is it correct, or has anyone a better routine ?

Thanx
Giulio

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: red floyd on
On Aug 5, 1:00 pm, Giulio Guarnone <giulio.guarn...(a)gmail.com> wrote:
> Hi to all,
>
> I've written down this function for perfoming endian conversion :
>
> template<typename T>
> T swap_endian(const T& source)
> {
> T ret = 0;
>
> for (int i = 0; i < sizeof(T); ++i)
> {
> *(reinterpret_cast<char*>(&ret) + i) =
> *(reinterpret_cast<char*>(&source) + sizeof(T) - i - 1);
> }
> return ret;
>
> }
>
> It seems to work the most of the times, but I'm not sure when I use it
> on signed types (int long etc etc) with negative numbers or with
> positive numbers like 1520 :
>
> bigendian 0x05F0
> littleendian 0xF005
>
> Is it correct, or has anyone a better routine ?
>

It looks to me like you're swapping each byte *twice*.

I think your loop should only go to sizeof(T)/2


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ulrich Eckhardt on
Giulio Guarnone wrote:
> I've written down this function for perfoming endian conversion :
>
> template<typename T>
> T swap_endian(const T& source)
> {
> T ret = 0;
>
> for (int i = 0; i < sizeof(T); ++i)
> {
> *(reinterpret_cast<char*>(&ret) + i) =
> *(reinterpret_cast<char*>(&source) + sizeof(T) - i - 1);
> }
> return ret;
> }
>
> It seems to work the most of the times, but I'm not sure when I use it
> on signed types (int long etc etc) with negative numbers or with
> positive numbers [...]

There is one problem, and that is that byte-swapping might yield an invalid
value for a T. Also, logically, the result is not a T but a byte-buffer
containing the byte-swapped represention for a T. Of course, other problems
also arise when you try to use this function with anything but very simple
datatypes.

Other than that, the code is correct. Since you only take bytes (char) and
move them around, the type of the underlying object is irrelevant.

That said, the code is horrible to read. I'd introduce two local objects
containing the source and target addresses and then use x[i] for indexing
instead of *(x+i). Further, you could make it a bit more generic by
initialising 'ret' with 'T()' instead of '0'. However, you don't need to
initialise it at all, since it is completely overwritten anyway.


BTW, in reply to red floyd's, he's wrong. I guess he overlooked that you are
not byte-swapping in place but rather copying. Maybe he got confused be the
function name, I got confused by it, too.

Uli

--
Sator Laser GmbH
Gesch�ftsf�hrer: Thorsten F�cking, Amtsgericht Hamburg HR B62 932


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Stefan van Kessel on
On 8/6/2010 5:36 AM, red floyd wrote:
> On Aug 5, 1:00 pm, Giulio Guarnone<giulio.guarn...(a)gmail.com> wrote:
>> template<typename T>
>> T swap_endian(const T& source)
>> {
>> T ret = 0;
>>
>> for (int i = 0; i< sizeof(T); ++i)
>> {
>> *(reinterpret_cast<char*>(&ret) + i) =
>> *(reinterpret_cast<char*>(&source) + sizeof(T) - i - 1);
>> }
>> return ret;
>>
>> }


> It looks to me like you're swapping each byte *twice*.
>
> I think your loop should only go to sizeof(T)/2

The code doesn't actually swap but just sets T byte for byte from back of source to front of source, leaving source itself intact. So sizeof(T) is correct.

Just one minor mistake: *(reinterpret_cast<char*>(&source) should be *(reinterpret_cast<const char*>(&source). &source is pointer to const and the compiler shouldn't allow a reinterpret_cast to a pointer to non const.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Jens Schmidt on
red floyd wrote:

> On Aug 5, 1:00 pm, Giulio Guarnone <giulio.guarn...(a)gmail.com> wrote:
>> template<typename T>
>> T swap_endian(const T& source)
>> {
>> T ret = 0;
>>
>> for (int i = 0; i < sizeof(T); ++i)
>> {
>> *(reinterpret_cast<char*>(&ret) + i) =
>> *(reinterpret_cast<char*>(&source) + sizeof(T) - i - 1);
>> }
>> return ret;
>>
>> }
>
> It looks to me like you're swapping each byte *twice*.

No, he is not. He is swapping while copying from source to ret.

> I think your loop should only go to sizeof(T)/2

That is for in-place swapping only. You can't do in-place swapping
with a const T&.

A real problem I see: after swapping the value is no longer of
type T, but just a sequence of bytes. This might be fatal for the
program if T is float or double and accidentially the result is
the pattern of a signaling NaN.
--
Greetings,
Jens Schmidt


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]