473,406 Members | 2,816 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

Endian Independence

#include<stdio.h>

#define LITTLE_ENDIAN 0
#define BIG_ENDIAN 1

int endian() {
int i = 1;
char *p = (char *)&i;

if (p[0] == 1)
return LITTLE_ENDIAN;
else
return BIG_ENDIAN;
}
int reverseInt (int i) {
unsigned char c1, c2, c3, c4;

if ( endian() == BIG_ENDIAN ) {
return i;
} else {
c1 = i & 255;
c2 = (i >8) & 255;
c3 = (i >16) & 255;
c4 = (i >24) & 255;

return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}
}

int main(void)
{
if(endian())
puts("Big Endian Machine");
else
puts("Small Endian Machine");
printf("%d",reverseInt(5));
return 0;

}

I tested it on my PC (On Pentium 4) and this is the output:

Small Endian Machine
83886080.

I am baffled as I was expecting 5 to be printed or is it that I am
missing something completely ?
Probably i have completely misunderstood the idea of endianness :(

Any help is appreciated.

Thank You

Jul 27 '08 #1
17 2062
On 27 Jul 2008 at 15:41, Kelly B wrote:
int reverseInt (int i) {
unsigned char c1, c2, c3, c4;

if ( endian() == BIG_ENDIAN ) {
return i;
} else {
c1 = i & 255;
c2 = (i >8) & 255;
c3 = (i >16) & 255;
c4 = (i >24) & 255;

return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;
}
}

int main(void)
{
if(endian())
puts("Big Endian Machine");
else
puts("Small Endian Machine");
printf("%d",reverseInt(5));
return 0;
}

I tested it on my PC (On Pentium 4) and this is the output:

Small Endian Machine
83886080.

I am baffled as I was expecting 5 to be printed or is it that I am
missing something completely ?
Your (somewhat poorly named) reverseInt function takes an integer i, and
returns 32 bits that give i when interpreted as a bigendian integer.
Since your machine is littleendian, the printf() function interprets its
arguments as if they were littleendian, so when you pass printf
reversInt(5) as an argument, it interprets this as 0x05000000.

Jul 27 '08 #2
Kelly B <ke****@gmail.comwrites:

<snip>
This is what bugged me :(

http://www.ibm.com/developerworks/ai...ry/au-endianc/

I thought the article was correct and wanted to quickly test it on my
PC.
Well, it is not a good explanation, but it is not exactly wrong
either. The main part you missed is that you don't need to worry
unless your program "exports" multi-byte values. The vast majority of
C programs can be entirely portable without any need to worry about
the endianness of the hardware.

It is not surprising. That article has a section "When endianness
affects code" which has 6 paragraphs. 5 of these about when it does
*not* affect the code! Only that last short paragraph starts to explain
when it does matter.
>I guess i will have to write my own function(s).
If you are writing network code (the most common reason to export
multi-byte values) then you can use POSIX functions like htons and
htonl etc. Only write your own if you don't have these available or
you need to something more outlandish.

--
Ben.
Jul 27 '08 #3
Kelly B wrote:
#include<stdio.h>

#define LITTLE_ENDIAN 0
#define BIG_ENDIAN 1

int endian() {
int i = 1;
char *p = (char *)&i;

if (p[0] == 1)
return LITTLE_ENDIAN;
else
return BIG_ENDIAN;
}
...snip..

Just one more thing.What is the right way to convert a *signed* int from
one endianness to another ( more specifically from big-endian to small
or vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow
preserve the sign and treat the number as an unsigned int or am i
way-off again ?
Jul 27 '08 #4
Kelly B wrote:
Kelly B wrote:
>#include<stdio.h>

#define LITTLE_ENDIAN 0
#define BIG_ENDIAN 1

int endian() {
int i = 1;
char *p = (char *)&i;

if (p[0] == 1)
return LITTLE_ENDIAN;
else
return BIG_ENDIAN;
}

..snip..

Just one more thing.What is the right way to convert a *signed* int
from one endianness to another ( more specifically from big-endian to
small or vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow
preserve the sign and treat the number as an unsigned int or am i
way-off again ?
You'll need to the manner in which signed values are represented on your
machine, whether twos-complement, sign-and-magnitude or
ones-complement, the three formats that C recognises. Such code will
not be portable.

But most system's already provide their own routines for
endian-conversion whereever it's likely to matter. Unix systems provide
htonl/htons and ntohl/ntohs.

Jul 27 '08 #5

"Kelly B" <ke****@gmail.comwrote in message
Just one more thing.What is the right way to convert a *signed* int from
one endianness to another ( more specifically from big-endian to small or
vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow preserve
the sign and treat the number as an unsigned int or am i way-off again ?
Endianness isn't a problem, -2 is 11111111 11111110 on any two's complement
machine (in practical terms, on any machine), if your integers are 16 bits.
A little endian machine just swaps the two so the first byte becomes last in
memory.

The problem comes when trying to convert a 16-bit signed number to a 32 bit
signed number. You need to sign extend. This is easy enough to do in
principle using C, simply check the sign bit. If it is set, set your intial
integer to minus one, or all bits set. If it is clear, set to zero. Then
shift your bits in.
In practise it can be quite tricky to make sure you are shifting legally and
portably.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jul 27 '08 #6
santosh <sa*********@gmail.comwrites:
Kelly B wrote:
>Kelly B wrote:
>>#include<stdio.h>

#define LITTLE_ENDIAN 0
#define BIG_ENDIAN 1

int endian() {
int i = 1;
char *p = (char *)&i;

if (p[0] == 1)
return LITTLE_ENDIAN;
else
return BIG_ENDIAN;
}

..snip..

Just one more thing.What is the right way to convert a *signed* int
from one endianness to another ( more specifically from big-endian to
small or vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow
preserve the sign and treat the number as an unsigned int or am i
way-off again ?

You'll need to the manner in which signed values are represented on your
machine, whether twos-complement, sign-and-magnitude or
ones-complement, the three formats that C recognises. Such code will
not be portable.
Are you sure?

short int htohl(short int x)
{
short int r;
unsigned char *rp = (void *)&r, *xp = (void *)&x;
assert(sizeof x == 2);
rp[0] = xp[1];
rp[1] = xp[0];
return r;
}

Does this code not work on some systems? I can't see why not.
Obviously there are some systems on which the result is a trap
representation, but you are stuck in those cases anyway. This code
will even swap the bytes when x contains a trap representation (I
think).

--
Ben.
Jul 27 '08 #7
Antoninus Twink <no****@nospam.invalidwrites:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
>First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.

Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.
Heathfield said something similar a while back. I was shocked. Yes,
"system specific" etc but to try an claim "portable C" deals with endian
issues is garbage from what I've seen attempted in the real world.

Jul 27 '08 #8
In article <g6**********@registered.motzarella.org>,
Richard <rg****@gmail.comwrote:
>Antoninus Twink <no****@nospam.invalidwrites:
>On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
>>First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.

Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.

Heathfield said something similar a while back. I was shocked. Yes,
"system specific" etc but to try an claim "portable C" deals with endian
issues is garbage from what I've seen attempted in the real world.
Comment:
(I'm surprised no one had posted this yet - in this go around of this
classic thread)

Post:
Actually, the CLC dogma on this subject is that the only portable way
(and thus, the only that can be considered) is to write it out as ASCII
(oops, I think that might be a dirty word as well), er, I mean, "text",
and then read it back as text.

Jul 27 '08 #9
>"Kelly B" <ke****@gmail.comwrote in message
>Just one more thing.What is the right way to convert a *signed* int from
one endianness to another ( more specifically from big-endian to small or
vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow preserve
the sign and treat the number as an unsigned int or am i way-off again ?
In article <3o******************************@bt.com>
Malcolm McLean <re*******@btinternet.comwrote:
>Endianness isn't a problem, -2 is 11111111 11111110 on any two's complement
machine (in practical terms, on any machine), if your integers are 16 bits.
A little endian machine just swaps the two so the first byte becomes last in
memory.

The problem comes when trying to convert a 16-bit signed number to a 32 bit
signed number. You need to sign extend. This is easy enough to do in
principle using C, simply check the sign bit. If it is set, set your intial
integer to minus one, or all bits set. If it is clear, set to zero. Then
shift your bits in.
In practise it can be quite tricky to make sure you are shifting legally and
portably.
It is not that hard at all.

We had this entire discussion back in January of 2003:

<http://groups.google.com/group/comp.lang.c/browse_thread/thread/93ffeb6ad212002f/cb3c3ff9894d850f?hl=en&lnk=st&q=#cb3c3ff9894d850f>
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
Jul 27 '08 #10
Chris Torek <no****@torek.netwrites:
>>"Kelly B" <ke****@gmail.comwrote in message
>>Just one more thing.What is the right way to convert a *signed* int from
one endianness to another ( more specifically from big-endian to small or
vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow preserve
the sign and treat the number as an unsigned int or am i way-off again ?

In article <3o******************************@bt.com>
Malcolm McLean <re*******@btinternet.comwrote:
>>Endianness isn't a problem, -2 is 11111111 11111110 on any two's complement
machine (in practical terms, on any machine), if your integers are 16 bits.
A little endian machine just swaps the two so the first byte becomes last in
memory.

The problem comes when trying to convert a 16-bit signed number to a 32 bit
signed number. You need to sign extend. This is easy enough to do in
principle using C, simply check the sign bit. If it is set, set your intial
integer to minus one, or all bits set. If it is clear, set to zero. Then
shift your bits in.
In practise it can be quite tricky to make sure you are shifting legally and
portably.

It is not that hard at all.

We had this entire discussion back in January of 2003:

<http://groups.google.com/group/comp.lang.c/browse_thread/thread/93ffeb6ad212002f/cb3c3ff9894d850f?hl=en&lnk=st&q=#cb3c3ff9894d850f>
With all due respect Chris, I dont think I saw a thread which made
anything appear harder. It includes "don't bother" advice.
Jul 27 '08 #11
Chris Torek wrote:
>"Kelly B" <ke****@gmail.comwrote in message
>>Just one more thing.What is the right way to convert a *signed* int from
one endianness to another ( more specifically from big-endian to small or
vice versa). How do i preserve the *sign* bit.
Swapping the bytes cannot be an option, unless i probably somehow preserve
the sign and treat the number as an unsigned int or am i way-off again ?

In article <3o******************************@bt.com>
Malcolm McLean <re*******@btinternet.comwrote:
>Endianness isn't a problem, -2 is 11111111 11111110 on any two's complement
machine (in practical terms, on any machine), if your integers are 16 bits.
A little endian machine just swaps the two so the first byte becomes last in
memory.

The problem comes when trying to convert a 16-bit signed number to a 32 bit
signed number. You need to sign extend. This is easy enough to do in
principle using C, simply check the sign bit. If it is set, set your intial
integer to minus one, or all bits set. If it is clear, set to zero. Then
shift your bits in.
In practise it can be quite tricky to make sure you are shifting legally and
portably.

It is not that hard at all.

We had this entire discussion back in January of 2003:

<http://groups.google.com/group/comp.lang.c/browse_thread/thread/93ffeb6ad212002f/cb3c3ff9894d850f?hl=en&lnk=st&q=#cb3c3ff9894d850f>
Probably this is what i was looking for !
Thank You everyone for the help.
Much Appreciated.
Jul 27 '08 #12
Antoninus Twink <no****@nospam.invalidwrote:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.
Those who export for external consumption binary integers in non-bigendian
format invoke undefined behavior, like have daemons forced through their
nose, or having large anvils dropped on their head.

Heed the logic of self-preservation.

Jul 28 '08 #13
William Ahern <wi*****@wilbur.25thandClement.comwrites:
Antoninus Twink <no****@nospam.invalidwrote:
>On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
>Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.

Those who export for external consumption binary integers in non-bigendian
format invoke undefined behavior, like have daemons forced through their
nose, or having large anvils dropped on their head.

Heed the logic of self-preservation.
Maybe I'm slow today but I didn't understand a word of what you just
said or have a clue as to what you are suggesting.

And I'm still to say a clear and concise answer to Endian issues.

The bottom line is that any program which feeds on an externally
produced binary file must surely know the endianness of the data
therein. And the unit sizes.
Jul 28 '08 #14
On 27 Jul, 19:06, Richard<rgr...@gmail.comwrote:
Antoninus Twink <nos...@nospam.invalidwrites:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.
isn't that what he said? "Transferring binary values through a file"
includes reading the values.

Heathfield said something similar a while back.
to whom? Twink or Lew Pitcher?

I was shocked. Yes,
"system specific" etc but to try an claim "portable C" deals with endian
issues is garbage from what I've seen attempted in the real world.
?? I've had to worry about endianess in data transferred between
machines. In what way is this not "real world". Admittedly doing
in text tends to avoid the problem.
--
Nick Keighley

Unpredictability may be exciting, but I don't believe it constitutes
good programming practice.
Richard Heathfield
Jul 28 '08 #15
On 28 Jul, 04:45, Richard<rgr...@gmail.comwrote:
William Ahern <will...@wilbur.25thandClement.comwrites:
Antoninus Twink <nos...@nospam.invalidwrote:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.
Those who export for external consumption binary integers in non-bigendian
format invoke undefined behavior, like have daemons forced through their
nose, or having large anvils dropped on their head.
this makes no sense. Why not little endian or DEC's strange
"endian" format? The two ends simply have to agree.

Heed the logic of self-preservation.

Maybe I'm slow today but I didn't understand a word of what you just
said or have a clue as to what you are suggesting.
I thought I understood it. I thought it was wrong.

And I'm still to say a clear and concise answer to Endian issues.

The bottom line is that any program which feeds on an externally
produced binary file must surely know the endianness of the data
therein. And the unit sizes
yes.

I must have misunderstood one of your earlier posts where
I thought you contradicted this advice. My apologies.
--
Nick Keighley

Jul 28 '08 #16
Richard <rg****@gmail.comwrote:
William Ahern <wi*****@wilbur.25thandClement.comwrites:
Antoninus Twink <no****@nospam.invalidwrote:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.
Those who export for external consumption binary integers in non-bigendian
format invoke undefined behavior, like have daemons forced through their
nose, or having large anvils dropped on their head.

Heed the logic of self-preservation.
Maybe I'm slow today but I didn't understand a word of what you just
said or have a clue as to what you are suggesting.
It's late. Perhaps a poor attempt at humor. It was a round-about way of
commenting on the two previous posts, but I wasn't very specific. One
doesn't need to know the endianess of another machine to parse exchanged
data. Rather, one only needs to know the format of the data. Likewise, when
"trasferring binary values through a file", the compiler doesn't matter, the
data does (though the data format may be defined in terms of the compiler
specification, or in practice more likely treated as opaque vectors from
memory space, but then you're not really exchanging _between_ applications,
only among application processes). Finally, general preferred practice is to
use big-endian formats, because it lessens the guess-work and investigation
needed altogether... well, and for other reasons, like symmetry with C bit
operators when parsing byte streams.
And I'm still to say a clear and concise answer to Endian issues.
The bottom line is that any program which feeds on an externally
produced binary file must surely know the endianness of the data
therein. And the unit sizes.
Right... of the data.

Jul 28 '08 #17

Nick Keighley <ni******************@hotmail.comwrites:
On 27 Jul, 19:06, Richard<rgr...@gmail.comwrote:
>Antoninus Twink <nos...@nospam.invalidwrites:
On 27 Jul 2008 at 16:12, Lew Pitcher wrote:
>First off, as far as the C language is concerned, there is no need to
determine the "endianness" of stored values. Where it is important (i.e.
when transferring binary values through a file), your compiler's
documentation should tell you the exact format. Otherwise, you don't need
to worry about it.
Rubbish. Suppose he wants to read a binary file produced by someone else
on a different machine. Then knowing the endianness of both machines is
crucial.

isn't that what he said? "Transferring binary values through a file"
includes reading the values.

>Heathfield said something similar a while back.

to whom? Twink or Lew Pitcher?

>I was shocked. Yes,
"system specific" etc but to try an claim "portable C" deals with endian
issues is garbage from what I've seen attempted in the real world.

?? I've had to worry about endianess in data transferred between
machines. In what way is this not "real world". Admittedly doing
in text tends to avoid the problem.
Yes, so have I. And the program needed to be told which way things
were. And using text is laughable in many cases.

Jul 28 '08 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
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. ...
8
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 }
14
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...
2
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 }
33
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
8
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....
3
RRick
by: RRick | last post by:
This was a question that showed up in a job interview once. (And to answer your next question: No, I didn't :)) Write a subroutine that returns a bool on whether a system supports big endian...
23
by: guthena | last post by:
Write a small C program to determine whether a machine's type is little-endian or big-endian.
23
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."); }
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.