Ray
2010-02-24 20:54:05 UTC
Hello,
Here is an issue I should know, but I just realized I'm not quite sure. Of
course, the endianness of a multibyte scalar object is defined by whether the
least significant byte occupies the lowest address (little endian) or the
highest address (big endian), (I'm not concerned about "middle endian" here).
And of course, taking the "sizeof" any object produces a count of the number
of bytes of storage used by that object. For most scalar types on most
implementations all of those storage bytes are used to actually represent the
object's value. That is, a 4-byte int actually occupies exactly 4 bytes of
storage, an 8-byte double actually occupies 8 bytes of storage. However, in
some cases more storage is used for an object than is actually used to
represent the object's value. For example, only 10 or 12 bytes may be needed
to represent the value of a long double, but on some implementations 6 or 4
additional bytes of padding may be used to enforce 16-byte memory alignment,
and when such a padded object is written to a file, all padding is included.
Assuming that my description is accurate, my concern is regarding the
appropriate way to reverse the endian of such an object. Obviously for an
object that uses all of its storage to represent its value, reversing endian
simply amounts to exchanging the lowest-addressed storage byte with the
highest-addressed storage byte and working your way toward the middle,
something like the code that follows. However, in the case of an object that
doesn't use all of its storage to represent its value, the padding byte(s)
will be swapped with some of the value bytes, which I believe is not what is
desired. Instead, the swap should begin with the highest-addressed byte that
is actually used for the object's value, totally ignoring the padding bytes
themselves. Am I correct in this assumption? Assuming I am correct, I'm at
a loss for a simple portable way to determine how many bytes are used for the
value and how many are used for padding. Of course this can be determined by
looking at the compiler's documentation, but then portability goes out the
window. I can also envision using some bit shifting scheme to determine
this, but this would only work for objects with integral types. What do you
think?
Thanks,
Sonny
void *ReverseEndian(void *p, size_t size)
{
char *head = (char *)p;
char *tail = head + size - 1;
for (; tail > head; --tail, ++head)
{
char temp = *head;
*head = *tail;
*tail = temp;
}
return p;
}
int main(void)
{
int x;
long double y;
ReverseEndian((void *)&x, sizeof(x));
ReverseEndian((void *)&y, sizeof(y));
return 0;
}
Here is an issue I should know, but I just realized I'm not quite sure. Of
course, the endianness of a multibyte scalar object is defined by whether the
least significant byte occupies the lowest address (little endian) or the
highest address (big endian), (I'm not concerned about "middle endian" here).
And of course, taking the "sizeof" any object produces a count of the number
of bytes of storage used by that object. For most scalar types on most
implementations all of those storage bytes are used to actually represent the
object's value. That is, a 4-byte int actually occupies exactly 4 bytes of
storage, an 8-byte double actually occupies 8 bytes of storage. However, in
some cases more storage is used for an object than is actually used to
represent the object's value. For example, only 10 or 12 bytes may be needed
to represent the value of a long double, but on some implementations 6 or 4
additional bytes of padding may be used to enforce 16-byte memory alignment,
and when such a padded object is written to a file, all padding is included.
Assuming that my description is accurate, my concern is regarding the
appropriate way to reverse the endian of such an object. Obviously for an
object that uses all of its storage to represent its value, reversing endian
simply amounts to exchanging the lowest-addressed storage byte with the
highest-addressed storage byte and working your way toward the middle,
something like the code that follows. However, in the case of an object that
doesn't use all of its storage to represent its value, the padding byte(s)
will be swapped with some of the value bytes, which I believe is not what is
desired. Instead, the swap should begin with the highest-addressed byte that
is actually used for the object's value, totally ignoring the padding bytes
themselves. Am I correct in this assumption? Assuming I am correct, I'm at
a loss for a simple portable way to determine how many bytes are used for the
value and how many are used for padding. Of course this can be determined by
looking at the compiler's documentation, but then portability goes out the
window. I can also envision using some bit shifting scheme to determine
this, but this would only work for objects with integral types. What do you
think?
Thanks,
Sonny
void *ReverseEndian(void *p, size_t size)
{
char *head = (char *)p;
char *tail = head + size - 1;
for (; tail > head; --tail, ++head)
{
char temp = *head;
*head = *tail;
*tail = temp;
}
return p;
}
int main(void)
{
int x;
long double y;
ReverseEndian((void *)&x, sizeof(x));
ReverseEndian((void *)&y, sizeof(y));
return 0;
}