What is the fastest way to convert __int64 type from BigEndian To Little
Endian?
I wrote this function:
---
uint64 EndianReverse(uint64 number) {
typedef unsigned __int8 uint8;
const int size = sizeof(uint64);
uint8 polje[size] = {0};
uint8 *ptr = reinterpret_cast<uint8*>(&number);
int index = 0;
for (int i=size-1 ; i>=0 ; i--) {
polje[index] = *(ptr+i);
index++;
}
uint64 *retPtr = reinterpret_cast<uint64*>(polje);
return *retPtr;
}
---
but i know there is faster way with logical and shift opertors, so if anyone
knows it i would be appreciated. 11 4111
Tosha wrote: What is the fastest way to convert __int64 type from BigEndian To Little Endian? I wrote this function: --- uint64 EndianReverse(uint64 number) { typedef unsigned __int8 uint8; const int size = sizeof(uint64); uint8 polje[size] = {0}; uint8 *ptr = reinterpret_cast<uint8*>(&number); int index = 0; for (int i=size-1 ; i>=0 ; i--) { polje[index] = *(ptr+i); index++; } uint64 *retPtr = reinterpret_cast<uint64*>(polje); return *retPtr; } ---
but i know there is faster way with logical and shift opertors, so if anyone knows it i would be appreciated.
The "fastness" has to be _measured_, not deduced from the types of
operations used. That said, I'd expect this to be a bit faster:
template<class T> T EndianReverse(T t)
{
unsigned char uc[sizeof t];
memcpy(uc, &t, sizeof t);
for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; ++b, --e)
std::swap(*b, *e);
memcpy(&t, uc, sizeof t);
return t;
}
.... and it is (just measured), by about 20%, on my machine.
V
--
Please remove capital As from my address when replying by mail
"Me" <an*****************@yahoo.com> wrote in message
news:11**********************@p10g2000cwp.googlegr oups.com... Tosha wrote: What is the fastest way to convert __int64 type from BigEndian To Little Endian? <snip code>
Since it looks like you're on visual studio, how about trying the _byteswap_uint64 intrinsic:
http://msdn2.microsoft.com/en-us/lib...77(VS.80).aspx
Thank you very much.
Victor Bazarov wrote: Tosha wrote: What is the fastest way to convert __int64 type from BigEndian To Little Endian?
The "fastness" has to be _measured_, not deduced from the types of operations used. That said, I'd expect this to be a bit faster:
template<class T> T EndianReverse(T t) { unsigned char uc[sizeof t]; memcpy(uc, &t, sizeof t); for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); memcpy(&t, uc, sizeof t); return t; }
Why not do it inplace?
template<class T> void InplaceEndianReverse(T& t)
{
unsigned char* tp = reinterpret_cast<unsigned char *>(&t);
for (unsigned char *b = tp, *e = tp + sizeof(T) - 1; b < e; ++b, --e)
std::swap(*b, *e);
return;
}
Or saving at least one of the memcpy's in the out of place syntax?
template<class T> T EndianReverse(T t)
{
T result=t; // "hides" a memcpy.
unsigned char* tp = reinterpret_cast<unsigned char *>(&result);
for (unsigned char *b = tp, *e = tp + sizeof(T) - 1; b < e; ++b, --e)
std::swap(*b, *e);
return result;
}
Shouldn't this make a difference, especially if it is inlined?
Fabio
Fabio Fracassi wrote: Victor Bazarov wrote:
Tosha wrote: What is the fastest way to convert __int64 type from BigEndian To Little Endian? The "fastness" has to be _measured_, not deduced from the types of operations used. That said, I'd expect this to be a bit faster:
template<class T> T EndianReverse(T t) { unsigned char uc[sizeof t]; memcpy(uc, &t, sizeof t); for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); memcpy(&t, uc, sizeof t); return t; }
Why not do it inplace?
Because the behaviour in _your_ case is undefined. You're *not*
allowed to use the pointer obtained from 'reiterpret_cast' for
anything _except_ converting back to what it was.
template<class T> void InplaceEndianReverse(T& t) { unsigned char* tp = reinterpret_cast<unsigned char *>(&t); for (unsigned char *b = tp, *e = tp + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); return; }
Or saving at least one of the memcpy's in the out of place syntax?
template<class T> T EndianReverse(T t) { T result=t; // "hides" a memcpy. unsigned char* tp = reinterpret_cast<unsigned char *>(&result); for (unsigned char *b = tp, *e = tp + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); return result; }
Shouldn't this make a difference, especially if it is inlined?
Oh yes, I'll be it does, but in 'comp.lang.c++' it's customary to
suggest only _proper_ solutions, whose behaviour is well-defined
according to the International Standard of the C++ language. Both
your examples have undefined behaviour.
V
--
Please remove capital As from my address when replying by mail
Victor Bazarov wrote: Fabio Fracassi wrote: Victor Bazarov wrote:
template<class T> T EndianReverse(T t) { unsigned char uc[sizeof t]; memcpy(uc, &t, sizeof t); for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); memcpy(&t, uc, sizeof t); return t; }
Why not do it inplace?
Because the behaviour in _your_ case is undefined. You're *not* allowed to use the pointer obtained from 'reiterpret_cast' for anything _except_ converting back to what it was.
And what exactly is the point in converting it back and forth, without doing
anything in between?
Besides, the call to memcpy does two implicit casts, one from (T*) to
(void*) and one from (void*) to (unsigned char*), which is what allows you
to interpret the data as a series of bytes. Effectively your doing an
implicit cast from (T*) to (unsigned char*) with the memcpy. AFAIK,
reinterpret_cast does the same, albeit without the copying. template<class T> void InplaceEndianReverse(T& t) { unsigned char* tp = reinterpret_cast<unsigned char *>(&t); for (unsigned char *b = tp, *e = tp + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); return; }
[sniped one simmilar example] Shouldn't this make a difference, especially if it is inlined?
Oh yes, I'll be it does, but in 'comp.lang.c++' it's customary to suggest only _proper_ solutions, whose behaviour is well-defined according to the International Standard of the C++ language. Both your examples have undefined behaviour.
I think my example's have exactly the same behaviour as yours. We both let
the compiler interpret a typed pointer as another typed pointer. This might
be implementational defined behaviour, but I don't see a way around this.
Fabio
Fabio Fracassi wrote: Victor Bazarov wrote:
Fabio Fracassi wrote: Victor Bazarov wrote:
template<class T> T EndianReverse(T t) { unsigned char uc[sizeof t]; memcpy(uc, &t, sizeof t); for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; ++b, --e) std::swap(*b, *e); memcpy(&t, uc, sizeof t); return t; }
Why not do it inplace? Because the behaviour in _your_ case is undefined. You're *not* allowed to use the pointer obtained from 'reiterpret_cast' for anything _except_ converting back to what it was.
And what exactly is the point in converting it back and forth, without doing anything in between?
If there's no point, then do not do it.
Besides, the call to memcpy does two implicit casts, one from (T*) to (void*) and one from (void*) to (unsigned char*),
No. The call converts to void* only.
Anything else happens inside the implementation of memcpy.
And memcpy is an implementation problem.
Sure, most implementations will do what you say. But it is not guaranteed.
to interpret the data as a series of bytes. Effectively your doing an implicit cast from (T*) to (unsigned char*) with the memcpy. AFAIK, reinterpret_cast does the same, albeit without the copying.
That is what happens on most implementations, and on most
implementations your code actually does work.
Still there's nothing in the language definition that makes it
guaranteed. If I write a compiler that will do things differently, it
will still be a perfectly legal compiler.
I think my example's have exactly the same behaviour as yours. We both let the compiler interpret a typed pointer as another typed pointer. This might be implementational defined behaviour, but I don't see a way around this.
No. That is what your code tries to do. And is not legal.
His code converts to void* and calls memcpy. What happens inside memcpy
is that memory content is copyed. Without any type cast. The cast inside
memcpy is that of a magic spell.
AnalogFile wrote: Fabio Fracassi wrote: Victor Bazarov wrote:
Fabio Fracassi wrote: Victor Bazarov wrote:
> template<class T> T EndianReverse(T t) > { > unsigned char uc[sizeof t]; > memcpy(uc, &t, sizeof t); > for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; > ++b, --e) std::swap(*b, *e); > memcpy(&t, uc, sizeof t); > return t; > } > Why not do it inplace? Because the behaviour in _your_ case is undefined. You're *not* allowed to use the pointer obtained from 'reiterpret_cast' for anything _except_ converting back to what it was.
And what exactly is the point in converting it back and forth, without doing anything in between?
If there's no point, then do not do it.
What is the point of having it in the language then? And how could I solve
such problems without relying on undefined behaviour? Besides, the call to memcpy does two implicit casts, one from (T*) to (void*) and one from (void*) to (unsigned char*),
No. The call converts to void* only. Anything else happens inside the implementation of memcpy.
I don't think so. memcpy doesn't know anything about types, and does no
casting whatsoever. Its signature is "void* memcpy(void* dest, const void*
src, size_t n);". So if someone uses a typed pointer in memcpy's dest
parameter there is an implicit cast from void* to the type which was used.
As long as the cast doesn't change the bit pattern of the pointed to values
this operation is save.
Fabio
Fabio Fracassi wrote: AnalogFile wrote:
Fabio Fracassi wrote: Victor Bazarov wrote:
Fabio Fracassi wrote: > Victor Bazarov wrote: > >> template<class T> T EndianReverse(T t) >> { >> unsigned char uc[sizeof t]; >> memcpy(uc, &t, sizeof t); >> for (unsigned char *b = uc, *e = uc + sizeof(T) - 1; b < e; >> ++b, --e) std::swap(*b, *e); >> memcpy(&t, uc, sizeof t); >> return t; >> } >> > Why not do it inplace? Because the behaviour in _your_ case is undefined. You're *not* allowed to use the pointer obtained from 'reiterpret_cast' for anything _except_ converting back to what it was. And what exactly is the point in converting it back and forth, without doing anything in between? If there's no point, then do not do it.
What is the point of having it in the language then?
I wrote "if" there's no point. It's in the language for those cases
where there actually is a point.
And how could I solve such problems without relying on undefined behaviour?
Use the system library. Besides, the call to memcpy does two implicit casts, one from (T*) to (void*) and one from (void*) to (unsigned char*), No. The call converts to void* only. Anything else happens inside the implementation of memcpy.
I don't think so. memcpy doesn't know anything about types, and does no casting whatsoever.
memcpy is part of the system and what it does or does not you cannot
say, except for the documented side effect of copying underlying bytes
from source to destination.
Its signature is "void* memcpy(void* dest, const void* casting whatsoever. Its signature is "void* memcpy(void* dest, const void* src, size_t n);". So if someone uses a typed pointer in memcpy's dest parameter there is an implicit cast from void* to the type which was used.
sorry. I do not understand the above.
AnalogFile wrote: Fabio Fracassi wrote: memcpy is part of the system and what it does or does not you cannot say, except for the documented side effect of copying underlying bytes from source to destination.
Its signature is "void* memcpy(void* dest, const void* casting whatsoever. Its signature is "void* memcpy(void* dest, const void* src, size_t n);". So if someone uses a typed pointer in memcpy's dest parameter there is an implicit cast from void* to the type which was used.
sorry. I do not understand the above.
I'm just saying that memcpy is not resposible for the reinterpreting of the
pointer types, but that it happens implicitly at the function call, i.e
T1* t1p;
T2* t2p;
memcpy (t2p, t1p, sizeof(T1));
is equivalent to:
T1* t1p;
T2* t2p;
void * v1p = (void*) t1p;
void * v2p = (void*) t2p;
memcpy (v2p, v1p, sizeof(T1));
After writeing this I see the subtle difference between this way an what I
have written, because in this case the "backward" cast from (void*) to
(T2*) never happens, because t2p already holds the correct address.
Now does the standard really not guarantee that the pointed to memory is
left alone when I do an reinterpret_cast? Could you point me the right
section where I could look this up?
I'm not trying to be argumentative, but I can't belive that something as
basic as an inplace endianess reversal can't be done without resorting to
undefined behaviour or system specific libraries. If it is I consider this
a Defect.
Fabio
Fabio Fracassi wrote: Its signature is "void* memcpy(void* dest, const void* casting whatsoever. Its signature is "void* memcpy(void* dest, const void* src, size_t n);". So if someone uses a typed pointer in memcpy's dest parameter there is an implicit cast from void* to the type which was used. sorry. I do not understand the above.
I'm just saying that memcpy is not resposible for the reinterpreting of the pointer types, but that it happens implicitly at the function call, i.e
T1* t1p; T2* t2p; memcpy (t2p, t1p, sizeof(T1));
is equivalent to:
T1* t1p; T2* t2p;
void * v1p = (void*) t1p; void * v2p = (void*) t2p; memcpy (v2p, v1p, sizeof(T1));
After writeing this I see the subtle difference between this way an what I have written, because in this case the "backward" cast from (void*) to (T2*) never happens, because t2p already holds the correct address.
Neither of the above sequences ever does any backward cast from void*
They in fact are perfectly equivalent.
Now does the standard really not guarantee that the pointed to memory is left alone when I do an reinterpret_cast? Could you point me the right section where I could look this up?
I'm again not sure I understand you.
If I get it right then, the "pointed to" memory does not change. Not at
the time of the cast.
I'm not trying to be argumentative, but I can't belive that something as basic as an inplace endianess reversal can't be done without resorting to undefined behaviour or system specific libraries. If it is I consider this a Defect.
If you think hard at it you realize that the very concept of "endianness
reversal" is totally system dependent.
You are assuming that the system does have some sort of endianness to
begin with. Like a 4 bytes value is either stored as 1234 or 4321. And
probably you also assume values to be 2s complement. But as far as the
language is concerned it may be 1423 and not be 2s complement! This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Joe C |
last post by:
I have some code that performs bitwise operations on files. I'm trying to
make the code portable on different endian systems. This is not work/school
related...just trying to learn/understand.
...
|
by: Perception |
last post by:
Hello all,
If I have a C-like data structure such that
struct Data {
int a; //16-bit value
char; //3 ASCII characters
int b; //32-bit value
int c; //24-bit value
}
|
by: ThazKool |
last post by:
I want to see if this code works the way it should on a Big-Endian
system. Also if anyone has any ideas on how determine this at
compile-time so that I use the right decoding or encoding...
|
by: bhatia |
last post by:
Hello all,
If I have a C-like data structure such that
struct Data {
int a; //16-bit value
char; //3 ASCII characters
int b; //32-bit value
int c; //24-bit value
}
|
by: Frederick Gotham |
last post by:
I was intrigued by someone the other day who posted regarding methods of
"mirror-imaging" the bits in a byte. I thought it might be interesting to
write a fully-portable algorithm for...
|
by: raghu |
last post by:
Is it possible to know whether a system is little endian or big endian
by writing a C program? If so, can anyone please give me the idea to
approach...
Thanks a ton.
Regards,
Raghu
|
by: ma740988 |
last post by:
Data stored on a storage device is byte swapped. The data is big
endian and my PC is little. At issue: There's a composite type ( a
header ) at the front of the files that I'm trying to read in....
|
by: guthena |
last post by:
Write a small C program to determine whether a machine's type is
little-endian or big-endian.
|
by: Niranjan |
last post by:
I have this program :
void main()
{
int i=1;
if((*(char*)&i)==1)
printf("The machine is little endian.");
else
printf("The machine is big endian.");
}
|
by: DolphinDB |
last post by:
Tired of spending countless mintues downsampling your data? Look no further!
In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
|
by: Defcon1945 |
last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
|
by: Shællîpôpï 09 |
last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
|
by: af34tf |
last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
|
by: Faith0G |
last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
| |