How to determine the byte order of machine.

S

somenath

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
 
B

Ben Bacarisse

somenath said:
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.
 
S

somenath

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


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?
 
H

Heinrich Wolf

somenath said:
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.
this instead (untested):

#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
 
H

Heinrich Wolf

....
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.
 
J

James Kuyper

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.
 
J

James Kuyper

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.
 
N

Noob

somenath said:
#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);
 
E

Eric Sosman

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.
 
B

BartC

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?).
 
B

BartC

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?).
 
J

Joachim Schmitz

BartC said:
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
 
B

Ben Bacarisse

somenath said:
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.
 
B

BartC

Joachim Schmitz said:
BartC wrote:

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
addressed.

Whether I'm right or wrong, it makes me glad I'm working with x86
byte-addressed little-endian, which doesn't do my head in so much..
 
N

Noob

BartC said:
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
addressed.

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

Joachim Schmitz

BartC said:
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 addressed.

I believe m68k is 32 bit.
 
S

somenath

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
over address.
 
J

Joe Pfeiffer

somenath said:
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?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top