# How to determine the byte order of machine.

Discussion in 'C Programming' started by somenath, Feb 20, 2012.

1. ### somenathGuest

Hello All,
Is the following program can correctly determine the byte order of the
machine?
#include<stdio.h>
int main(void)
{
unsigned int x =1;
if ((x>>1) == 0)
printf("little-endian\n");
else
printf("Big-endian \n");
return 0;
}
In my opinion in case of little endian the 1 will be stored at the
last byte of the variable x. so if I shift it 1 byte the variable x
will have 0.But in case of big-endian 1 will be store at the right
most bye so right shifting by 1 should not be obtain 0. Is my
understanding correct?
I did not have access to big-endian machine. So i have not checked the
program in big-endian machine.

Thanks.
Somenath

somenath, Feb 20, 2012

2. ### Ben BacarisseGuest

somenath <> writes:

> Hello All,
> Is the following program can correctly determine the byte order of the
> machine?

No. The output is independent of the way in which values are stored.

> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)
> printf("little-endian\n");
> else
> printf("Big-endian \n");
> return 0;
> }
> In my opinion in case of little endian the 1 will be stored at the
> last byte of the variable x. so if I shift it 1 byte the variable x
> will have 0.But in case of big-endian 1 will be store at the right
> most bye so right shifting by 1 should not be obtain 0. Is my
> understanding correct?

No. When x is unsigned (or signed and non-negative) x >> 1 is defined
to be the integer part of x/2. In effect, the shift operates on the
value bits in their value order.

> I did not have access to big-endian machine. So i have not checked the
> program in big-endian machine.

--
Ben.

Ben Bacarisse, Feb 20, 2012

3. ### somenathGuest

On Feb 20, 4:49 pm, Ben Bacarisse <> wrote:
> somenath <> writes:
> > Hello All,
> > Is the following program can correctly determine the byte order of the
> > machine?

>
> No.  The output is independent of the way in which values are stored.
>
> > #include<stdio.h>
> > int main(void)
> > {
> >     unsigned int x =1;
> >     if ((x>>1) == 0)
> > printf("little-endian\n");
> >     else
> >    printf("Big-endian \n");
> >     return 0;
> > }
> > In my opinion in case of little endian the 1 will be stored at the
> > last byte of the variable x. so if I shift it 1 byte the variable x
> > will have 0.But in case of big-endian 1 will  be store at the right
> > most bye so right shifting by 1 should not be obtain 0. Is my
> > understanding correct?

>
> No.  When x is unsigned (or signed and non-negative) x >> 1 is defined
> to be the integer part of x/2.  In effect, the shift operates on the
> value bits in their value order.
>

I did not get this point. could you please explain it in more detail
way?

somenath, Feb 20, 2012
4. ### Heinrich WolfGuest

"somenath" <> schrieb im Newsbeitrag
news:...
> Hello All,
> Is the following program can correctly determine the byte order of the
> machine?
> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)
> printf("little-endian\n");
> else
> printf("Big-endian \n");
> return 0;
> }
> In my opinion in case of little endian the 1 will be stored at the
> last byte of the variable x. so if I shift it 1 byte the variable x
> will have 0.But in case of big-endian 1 will be store at the right
> most bye so right shifting by 1 should not be obtain 0. Is my
> understanding correct?
> I did not have access to big-endian machine. So i have not checked the
> program in big-endian machine.
>
> Thanks.
> Somenath

Hi,

x >> 1 is always x / 2, that does not depend on the byte order. Try e.g.

#include <stdio.h>
int main(void)
{
typedef unsigned char t_b[2];
union {
t_b b;
unsigned short s;
} u;
u.s = 1;
if (u.b[0] == 1)
// u.b[1] == 0
printf("little-endian\n");
else
// u.b[0] == 0
// u.b[1] == 1
printf("big-endian\n");
return 0;
}

Heiner

Heinrich Wolf, Feb 20, 2012
5. ### Heinrich WolfGuest

....
> x >> 1 is always x / 2,

I'm sorry - not always, but normally under the condition, that Ben wrote
....

Heinrich Wolf, Feb 20, 2012
6. ### Heinrich WolfGuest

"somenath" <> schrieb im Newsbeitrag
news:...
....
> No. When x is unsigned (or signed and non-negative) x >> 1 is defined
> to be the integer part of x/2. In effect, the shift operates on the
> value bits in their value order.
>

I did not get this point. could you please explain it in more detail
way?

An example:
0x04030201
on a big endian machine is
0x04 0x03 0x02 0x01,
on a little endian machine is
0x01 0x02 0x03 0x04

0x04030201 >> 1 is 0x02018100
That is
0x02 0x01 0x81 0x00
on a big endian machine and
0x00 0x81 0x01 0x02
on a little endian machine.

Heinrich Wolf, Feb 20, 2012
7. ### James KuyperGuest

On 02/20/2012 06:35 AM, somenath wrote:
> Hello All,
> Is the following program can correctly determine the byte order of the
> machine?
> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)
> printf("little-endian\n");
> else
> printf("Big-endian \n");
> return 0;
> }

The expression E1 >> E2 has a value defined by the standard only for
non-negative x and non-negative values of E2 that are less than the
width of the type. When that is the case, the behavior defined by the
standard depends only upon the values of E1 and E2, and not on the way
that they are represented. Is is simply E1 / (2^E2); in this particular
case, that works out to 1/2, which is 0 according to C's rules for
integer division. The value of the result tells you nothing about the
byte order of unsigned int.
--
James Kuyper

James Kuyper, Feb 20, 2012
8. ### James KuyperGuest

On 02/20/2012 07:11 AM, somenath wrote:
> On Feb 20, 4:49ï¿½pm, Ben Bacarisse <> wrote:
>> somenath <> writes:
>>> Hello All,
>>> Is the following program can correctly determine the byte order of the
>>> machine?

>>
>> No. ï¿½The output is independent of the way in which values are stored.
>>
>>> #include<stdio.h>
>>> int main(void)
>>> {
>>> ï¿½ ï¿½ unsigned int x =1;
>>> ï¿½ ï¿½ if ((x>>1) == 0)
>>> printf("little-endian\n");
>>> ï¿½ ï¿½ else
>>> ï¿½ ï¿½printf("Big-endian \n");
>>> ï¿½ ï¿½ return 0;
>>> }
>>> In my opinion in case of little endian the 1 will be stored at the
>>> last byte of the variable x. so if I shift it 1 byte the variable x
>>> will have 0.But in case of big-endian 1 will ï¿½be store at the right
>>> most bye so right shifting by 1 should not be obtain 0. Is my
>>> understanding correct?

>>
>> No. ï¿½When x is unsigned (or signed and non-negative) x >> 1 is defined
>> to be the integer part of x/2. ï¿½In effect, the shift operates on the
>> value bits in their value order.
>>

> I did not get this point. could you please explain it in more detail
> way?

Let's keep it simple, by considering an implementation where
CHAR_BIT==8, and UINT_MAX is 65535. The bits that make up an unsigned
int therefore represent the values 1, 2, 4, 8, 16, 32, 64, 128, 256,
512, 1024, 2048, 4096, 8192, 16384. Let's assume that the first 8 of
those bits are stored in the one byte, and the remaining 8 are stored in
the other one, without bothering to identify which order those bytes are
in. Whatever the value stored in x is, the expression x >> 1 produces a
result that would correspond to taking the value of the bit that
represents 2, and moving it into the bit that represents 1; moving the
value of the bit that represents 4, into the bit that represents 2; etc.

The interesting case is the bit representing 256, the value of which
must be moved into the bit which represents 128, which is in a different
byte. Here's the important point - it must be moved into that bit,
regardles of whether the byte containing that bit occurs before or after
the byte containing the bit representing 256 in memory. The "right" in
"right shift" refers only the to values of the bits, it has nothing to
do with the order of the bytes containing those bits in memory.

Another key point: the value of the bit that represents 1 simply
disappears - it does not get moved into the bit representing 16384 (that
would be called a rotation, rather than a shift), nor does it get moved
anywhere else. The bit representing 16384 simply gets set to 0.
--
James Kuyper

James Kuyper, Feb 20, 2012
9. ### NoobGuest

somenath wrote:

> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)

1U >> 1 equals 0 on every C platform in the universe.

Consider

unsigned int x = 1;
unsigned char arr[sizeof x];
memcpy(arr, &x, sizeof x);

Noob, Feb 20, 2012
10. ### Eric SosmanGuest

On 2/20/2012 6:35 AM, somenath wrote:
> Hello All,
> Is the following program can correctly determine the byte order of the
> machine?

No.

> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)
> printf("little-endian\n");
> else
> printf("Big-endian \n");
> return 0;
> }

This code will print "little-endian\n" on all systems (barring
I/O errors and the like).

> In my opinion in case of little endian the 1 will be stored at the
> last byte of the variable x. so if I shift it 1 byte the variable x
> will have 0.But in case of big-endian 1 will be store at the right
> most bye so right shifting by 1 should not be obtain 0. Is my
> understanding correct?

No. For one thing, your explanations of little-endian and
big-endian seem rather confused; what do you mean, precisely, by
"last" and "right most?"

Even when the confusion is cleared up, you're missing the fact
that the `>>' operator (like most C operators) works with the values
of its operands, not with their representations. The `>>' operator
is most easily described in terms of a binary representation of its
first operand, and "right" shift suggests a certain way of writing
that representation -- but that doesn't mean the hardware actually
rolls bits around like so many tiny marbles. The bit that is discarded
by `>> 1' is the *least significant* bit, which in your example is
always 1 beforehand and 0 afterward.

> I did not have access to big-endian machine. So i have not checked the
> program in big-endian machine.

You should also be aware that "big-endian" and "little-endian"
do not exhaust all the possibilities. There have been "middle-endian"
machines, and "no-endian" CPU's are said to be fairly common among
digital signal processors and perhaps some supercomputers.

C requires that its unsigned integers behave "as if" written in
base 2 positional notation, with a 1's bit, 2's bit, 4's bit, and so
on. However, C says nothing at all about the arrangement of those
bits! For example, there is no rule requiring the 1's bit and the
2's bit to occupy the same byte of a multi-byte integer (it would
be perverse if they did not, but C tolerates perversity).

Your best bet is to write code that works with values, regardless
of how those values are represented. Ideally, you would not even
know how the machine represents eight hundred seventeen; you should
concern yourself with finding its factors or comparing it to nine
hundred twenty-six or whatever. It is occasionally necessary to
pierce the veil, but not very often.

--
Eric Sosman
d

Eric Sosman, Feb 20, 2012
11. ### BartCGuest

"somenath" <> wrote in message
news:...

> Is the following program can correctly determine the byte order of the
> machine?

I tried this:

char bytes[2]={1,2};

printf("%2X\n",*((short*)bytes));

On my machine, it printed 201, as I expected where the least-significant
byte occurs first in memory.

But I also knew that chars were 8 bits, and shorts were 16 bits. I think
also on some machines, the two 16-bit halves of a 32-bit value may be
mangled in some way (68000?).

--
Bartc

BartC, Feb 20, 2012
12. ### BartCGuest

"somenath" <> wrote in message
news:...

> Is the following program can correctly determine the byte order of the
> machine?

I tried this:

char bytes[2]={1,2};
printf("%2X\n",*((short*)bytes));

On my machine, it printed 201, as I expected where the least-significant
byte occurs first in memory.

I also tried:

char bytes[4]={1,2,3,4};
printf("%4X\n",*((int*)bytes));

And got 4030201, again as expected. However I knew my machine uses 8, 16 and
32-bit widths for char, short and int.

Other machines may give unexpected results, for example some mangled form of
{1,2,3,4} instead of 4030201 or 1020304 (68000?).

--
Bartc

BartC, Feb 20, 2012
13. ### Joachim SchmitzGuest

BartC wrote:
> "somenath" <> wrote in message
> news:...
>
>> Is the following program can correctly determine the byte order of
>> the machine?

>
> I tried this:
>
> char bytes[2]={1,2};
>
> printf("%2X\n",*((short*)bytes));
>
> On my machine, it printed 201, as I expected where the
> least-significant byte occurs first in memory.
>
> But I also knew that chars were 8 bits, and shorts were 16 bits. I
> think also on some machines, the two 16-bit halves of a 32-bit value
> may be mangled in some way (68000?).

m68k is big endian

Joachim Schmitz, Feb 20, 2012
14. ### Ben BacarisseGuest

somenath <> writes:

> On Feb 20, 4:49Â pm, Ben Bacarisse <> wrote:
>> somenath <> writes:
>> > Hello All,
>> > Is the following program can correctly determine the byte order of the
>> > machine?

>>
>> No. Â The output is independent of the way in which values are stored.
>>
>> > #include<stdio.h>
>> > int main(void)
>> > {
>> > Â  Â  unsigned int x =1;
>> > Â  Â  if ((x>>1) == 0)
>> > printf("little-endian\n");
>> > Â  Â  else
>> > Â  Â printf("Big-endian \n");
>> > Â  Â  return 0;
>> > }
>> > In my opinion in case of little endian the 1 will be stored at the
>> > last byte of the variable x. so if I shift it 1 byte the variable x
>> > will have 0.But in case of big-endian 1 will Â be store at the right
>> > most bye so right shifting by 1 should not be obtain 0. Is my
>> > understanding correct?

>>
>> No. Â When x is unsigned (or signed and non-negative) x >> 1 is defined
>> to be the integer part of x/2. Â In effect, the shift operates on the
>> value bits in their value order.
>>

> I did not get this point. could you please explain it in more detail
> way?

It's hard to do that. x >> 1 is simply defined to be the same as x/2.
I am sure that you agree that dividing an unsigned x by 2 (in the C
sense that does integer division) does not in any way depend on the way
the bytes are stored in the machine. x/2 is the same on all machines.
Similarly, x >> 1 is the same on all machines.

Now with signed ints things are a little more complex because the C
standard leave a few more things open for the compiler to decide, but
even there the basic operation is the same. >> moves high-order bits
into lower-order positions and << does the reverse. It does not matter
where or how these bits are stored, the effect is the same. 1 << 1 is 2
on all machines, and 4 >> 2 is 1 on all machines.

--
Ben.

Ben Bacarisse, Feb 20, 2012
15. ### BartCGuest

"Joachim Schmitz" <> wrote in message
news:jhtm6m\$jpk\$...
> BartC wrote:

>> But I also knew that chars were 8 bits, and shorts were 16 bits. I
>> think also on some machines, the two 16-bit halves of a 32-bit value
>> may be mangled in some way (68000?).

>
> m68k is big endian

I was probably thinking of something else where the representation was not
straightforward.

But even on the 68K, which had 16-bit-wide (8-bit accessible) memory, the
number 0xBBAA would be stored, I think, as (BBAA) or (BB,AA) byte addressed,
but 0xDDCCBBAA would be stored as (BBAA,DDCC), or (BB,AA,DD,CC) byte

Whether I'm right or wrong, it makes me glad I'm working with x86

--
Bartc

BartC, Feb 20, 2012
16. ### NoobGuest

BartC wrote:

> I was probably thinking of something else where the representation was not
> straightforward.
>
> But even on the 68K, which had 16-bit-wide (8-bit accessible) memory, the
> number 0xBBAA would be stored, I think, as (BBAA) or (BB,AA) byte addressed,
> but 0xDDCCBBAA would be stored as (BBAA,DDCC), or (BB,AA,DD,CC) byte

Are you thinking of middle-endian (or mixed-endian) as seen on the PDP-11?
http://en.wikipedia.org/wiki/Endianness#Middle-endian

Noob, Feb 20, 2012
17. ### Joachim SchmitzGuest

BartC wrote:
> "Joachim Schmitz" <> wrote in message
> news:jhtm6m\$jpk\$...
>> BartC wrote:

>
>>> But I also knew that chars were 8 bits, and shorts were 16 bits. I
>>> think also on some machines, the two 16-bit halves of a 32-bit value
>>> may be mangled in some way (68000?).

>>
>> m68k is big endian

>
> I was probably thinking of something else where the representation
> was not straightforward.
>
> But even on the 68K, which had 16-bit-wide (8-bit accessible) memory,
> the number 0xBBAA would be stored, I think, as (BBAA) or (BB,AA) byte
> addressed, but 0xDDCCBBAA would be stored as (BBAA,DDCC), or

I believe m68k is 32 bit.

> Whether I'm right or wrong, it makes me glad I'm working with x86

Joachim Schmitz, Feb 20, 2012
18. ### Nils M HolmGuest

Noob <root@127.0.0.1> wrote:
> Are you thinking of middle-endian (or mixed-endian) as seen on the PDP-11?
> http://en.wikipedia.org/wiki/Endianness#Middle-endian

Note, though, that this is merely a convention used by the compiler
in this case, as the 11 has no 32-bit store instructions.

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Nils M Holm, Feb 20, 2012
19. ### somenathGuest

On Feb 20, 7:52 pm, Ben Bacarisse <> wrote:
> somenath <> writes:
> > On Feb 20, 4:49 pm, Ben Bacarisse <> wrote:
> >> somenath <> writes:
> >> > Hello All,
> >> > Is the following program can correctly determine the byte order of the
> >> > machine?

>
> >> No.  The output is independent of the way in which values are stored..

>
> >> > #include<stdio.h>
> >> > int main(void)
> >> > {
> >> >     unsigned int x =1;
> >> >     if ((x>>1) == 0)
> >> > printf("little-endian\n");
> >> >     else
> >> >    printf("Big-endian \n");
> >> >     return 0;
> >> > }
> >> > In my opinion in case of little endian the 1 will be stored at the
> >> > last byte of the variable x. so if I shift it 1 byte the variable x
> >> > will have 0.But in case of big-endian 1 will  be store at the right
> >> > most bye so right shifting by 1 should not be obtain 0. Is my
> >> > understanding correct?

>
> >> No.  When x is unsigned (or signed and non-negative) x >> 1 is defined
> >> to be the integer part of x/2.  In effect, the shift operates on the
> >> value bits in their value order.

>
> > I did not get this point. could you please explain it in more detail
> > way?

>
> It's hard to do that.  x >> 1 is simply defined to be the same as x/2.
> I am sure that you agree that dividing an unsigned x by 2 (in the C
> sense that does integer division) does not in any way depend on the way
> the bytes are stored in the machine.  x/2 is the same on all machines.
> Similarly, x >> 1 is the same on all machines.
>
> Now with signed ints things are a little more complex because the C
> standard leave a few more things open for the compiler to decide, but
> even there the basic operation is the same.  >> moves high-order bits
> into lower-order positions and << does the reverse.  It does not matter
> where or how these bits are stored, the effect is the same.  1 << 1 is 2
> on all machines, and 4 >> 2 is 1 on all machines.
>

Thanks all for the explanation.
Actually I forgot the fact that the LSB or MSB of any byte never
depends on the the way bits are laid. LSB is always the 0th bit. The
0th bit may reside on address A or it may reside on A+32. So if int x
=1; x>>1 will always clear the LSB irrespective of the fact it is laid

somenath, Feb 20, 2012
20. ### Joe PfeifferGuest

somenath <> writes:

> Hello All,
> Is the following program can correctly determine the byte order of the
> machine?
> #include<stdio.h>
> int main(void)
> {
> unsigned int x =1;
> if ((x>>1) == 0)
> printf("little-endian\n");
> else
> printf("Big-endian \n");
> return 0;
> }
> In my opinion in case of little endian the 1 will be stored at the
> last byte of the variable x. so if I shift it 1 byte the variable x
> will have 0.But in case of big-endian 1 will be store at the right
> most bye so right shifting by 1 should not be obtain 0. Is my
> understanding correct?

No, there are at least two different misunderstandings underlying your
code:

(1) shifts work across the entire int, no matter what order the bytes of
the int appear in, in the underlying machine. So a shift by one
byte will result in an 8-bit shift across the entire word; it'll
give the same result whether the machine is big-endian or
little-endian.

(2) you aren't shifting by a byte, you're shifting by a bit. If it
weren't for the first misunderstanding your code would detect the
difference anyway, but it still wouldn't be doing what you expect.

If I wanted to check whether a machine were big-endian or little-endian,
my first choice would be to see whether the htonl macro (which converts
a host-order long to a network-order long, which we know in turn is
defined to be big-endian) changes anything. I expect that macro is
outside the scope of this newsgroup, since I'd be surprised if it were
part of the C standard.

You could also (on a machine with 8-bit bytes) declare an array of 4
chars, cast the array to a long and assign a value to it, then print the
values of the eight chars.

But, ummm... if the goal is really just to find out the answer, why not
look in an architecture manual for the machine?

Joe Pfeiffer, Feb 20, 2012