473,387 Members | 1,497 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,387 software developers and data experts.

Endian check macro

Hello all,
I tried to write a macro to check if a system is big endian or little endian
with no success. Don't get me wrong, I have no problem writing a function or
a one liner to do that, but I was trying to do it in a _macro_ with no
side-effect (no global variable declaration). I suspect this is not
possible.

Anyone cares to prove me wrong ?
--
Guillaume Dargaud
http://www.gdargaud.net/
Jul 8 '08 #1
13 5938
Guillaume Dargaud wrote:
Hello all,
I tried to write a macro to check if a system is big endian or little
endian with no success. Don't get me wrong, I have no problem writing
a function or a one liner to do that, but I was trying to do it in a
_macro_ with no side-effect (no global variable declaration). I
suspect this is not possible.

Anyone cares to prove me wrong ?
#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}

int main(void) {
ENDIAN();
return 0;
}

Jul 8 '08 #2
"Guillaume Dargaud" <us*****************************@www.gdargaud.ne t>
writes:
I tried to write a macro to check if a system is big endian or little endian
with no success. Don't get me wrong, I have no problem writing a function or
a one liner to do that, but I was trying to do it in a _macro_ with no
side-effect (no global variable declaration). I suspect this is not
possible.

Anyone cares to prove me wrong ?
In C99 you can use a compound literal to get something like the effect
you want[1]:

(union {short n; char b[sizeof(short)];}){.n = 1}.b[0]

Wrap, however you want it, in a macro. unsigned char might better in
general and there are a thousand issues with this code but without
some details of what you are doing, I can't suggest anything more
robust.

[1] I am wary of code that tests for endian-ness since I've used
machines where it is neither of the two commonly accepted
alternatives.

--
Ben.
Jul 8 '08 #3
On 8 Jul 2008 at 11:35, santosh wrote:
#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
That's a remarkably practical solution, Santosh. I'm surprised no one's
been along yet to warn you that (volatile unsigned char *)&ul might
contain a trap representation and dereferencing it cause UB, or some
such nonsense.

Jul 8 '08 #4
On Tue, 08 Jul 2008 18:56:59 +0000, Antoninus Twink wrote:
On 8 Jul 2008 at 11:35, santosh wrote:
>#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}

That's a remarkably practical solution, Santosh. I'm surprised no one's
been along yet to warn you that (volatile unsigned char *)&ul might
contain a trap representation and dereferencing it cause UB, or some
such nonsense.
(volatile unsigned char *)&ul is a value expression. Objects can contain
trap representations. Values cannot, since a trap representation, by
definition, does not represent a value.

If you were talking about *(volatile unsigned char *)&ul, then still,
unsigned char is not allowed to have trap representations. unsigned char
has 2**CHAR_BIT possible representations, and 2**CHAR_BIT possible values,
so each value corresponds to exactly one bit pattern, and vice versa.

If you were concerned with compatibility with C90, where accessing
indeterminate values is disallowed unconditionally, then the code is still
fine, because ul is initialised, and any object can be accessed as an
array of unsigned char.

There are some other comments that could be made about the code. I don't
see why volatile is necessary here, and there _might_ be a few machines
where the output is not factually correct. On those, the code is valid,
and you'll get one of the three outputs, not a crash, not garbage, not
anything else. (I'm not saying that's necessarily a good thing.) There is
no undefined behaviour that I can see.
Jul 8 '08 #5
santosh <sa*********@gmail.comwrites:
>Guillaume Dargaud wrote:
>Hello all,
I tried to write a macro to check if a system is big endian or little
endian with no success. Don't get me wrong, I have no problem writing
a function or a one liner to do that, but I was trying to do it in a
_macro_ with no side-effect (no global variable declaration). I
suspect this is not possible.

Anyone cares to prove me wrong ?
>#include <stdio.h>
>#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
>int main(void) {
ENDIAN();
return 0;
}

When the OP asked for a macro, and not a function, had I wrongly assumed
that the intent was that the macro would be evaluated at compile-time,
and not at run-time?

--
Chris.
Jul 8 '08 #6
santosh wrote:
Guillaume Dargaud wrote:
>I tried to write a macro to check if a system is big endian or
little endian with no success. Don't get me wrong, I have no
problem writing a function or a one liner to do that, but I was
trying to do it in a _macro_ with no side-effect (no global
variable declaration). I suspect this is not possible.

Anyone cares to prove me wrong ?

#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
... snip ...
Since (sizeof(long) == sizeof(char)) may be true, your first test
on *p can be satisfied without needing a little endian system.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Jul 8 '08 #7
On 8 Jul 2008 at 21:54, Gordon Burditt wrote:
*IF* your OS or compiler defines some preprocessor symbols that
will enable you to figure out endianness, you could cheat using
them. This is, of course, system-dependent. For example, on one
OS, in <machine/endian.hyou have:
[snip]

I believe an
#include <sys/types.h>
will define BYTE_ORDER on most(?) Unices - certainly on BSD and Linux
that's true. This will include machine-dependent endianness files for
you.

If the OP is aiming for portability, it's quite likely he'll be using
the GNU autotools, in which case he could check out some of their
macros, e.g. AC_C_BIGENDIAN etc.

Jul 8 '08 #8
On Jul 8, 5:08*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
[1] I am wary of code that tests for endian-ness since I've used
machines where it is neither of the two commonly accepted
alternatives.
But when we are reading binary packets which are not written on the
same architecture, or is following a particular style(tcp/ip uses big-
endian), we are forced to do the endian-ness tests.

Jul 9 '08 #9
rahul said:
On Jul 8, 5:08 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>[1] I am wary of code that tests for endian-ness since I've used
machines where it is neither of the two commonly accepted
alternatives.
But when we are reading binary packets which are not written on the
same architecture, or is following a particular style(tcp/ip uses big-
endian), we are forced to do the endian-ness tests.
Read what he's writing. He's saying that the assumption that an
architecture is either big-endian or little-endian is not always correct.
Middle-endian (sometimes called "NUXI") architectures do exist.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jul 9 '08 #10
CBFalconer wrote:
santosh wrote:
>Guillaume Dargaud wrote:
>>I tried to write a macro to check if a system is big endian or
little endian with no success. Don't get me wrong, I have no
problem writing a function or a one liner to do that, but I was
trying to do it in a _macro_ with no side-effect (no global
variable declaration). I suspect this is not possible.

Anyone cares to prove me wrong ?

#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
... snip ...

Since (sizeof(long) == sizeof(char)) may be true, your first test
on *p can be satisfied without needing a little endian system.
Yes, that is a problem with the code, but C90 is restricted to unsigned
long as the largest portable integral type, so the solution to this
might have to use non-portable code.

Jul 9 '08 #11
Chris McDonald wrote:
santosh <sa*********@gmail.comwrites:
>>Guillaume Dargaud wrote:
>>Hello all,
I tried to write a macro to check if a system is big endian or
little endian with no success. Don't get me wrong, I have no problem
writing a function or a one liner to do that, but I was trying to do
it in a _macro_ with no side-effect (no global variable
declaration). I suspect this is not possible.

Anyone cares to prove me wrong ?
>>#include <stdio.h>
>>#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
>>int main(void) {
ENDIAN();
return 0;
}


When the OP asked for a macro, and not a function, had I wrongly
assumed that the intent was that the macro would be evaluated at
compile-time, and not at run-time?
Hm, I didn't see it that way I admit. If the OP does want a compile-time
solution, then he might have to depend on non-standard headers, or
manually find out the endianness of the target and include the
appropriate defines. Executing a compile time program would not always
work if the target machine is not the machine that compiles the code.

Jul 9 '08 #12
Harald van D?k wrote:
>On 8 Jul 2008 at 11:35, santosh wrote:
>>#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}
[...]
There are some other comments that could be made about the code. I
don't see why volatile is necessary here,
I admit that I irrationally feared that the compiler might place the
variables in registers. Now I see that whatever it actually does, it
must still produce results according to the abstract machine, so yes,
the volatile is useless.
and there _might_ be a few
machines where the output is not factually correct.
Where sizeof(unsigned long) == sizeof(unsigned char). I suppose DSPs are
a possibility.
On those, the code
is valid, and you'll get one of the three outputs, not a crash, not
garbage, not anything else. (I'm not saying that's necessarily a good
thing.) There is no undefined behaviour that I can see.
Perhaps a style point, but would enclosing the code in a do/while loop
have been preferable to an unadorned block?

Jul 9 '08 #13
On 9 Jul 2008 at 5:30, rahul wrote:
But when we are reading binary packets which are not written on the
same architecture, or is following a particular style(tcp/ip uses big-
endian), we are forced to do the endian-ness tests.
Not necessarily - htons() and friends exist to abstract away this detail
for networking applications.

Jul 9 '08 #14

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

Similar topics

2
by: Marc Schellens | last post by:
Is there a standard conforming way to check for the endian of the current machine? Possibly at compile time? I am thinking of something like: union endian { char c; unsigned int i; };
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 }
11
by: Steve | last post by:
Hi, i know this is an old question (sorry) but its a different problem, i need to write a binary file as follows 00000011 00000000 00000000 00000101 00000000 11111111
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 }
5
by: manishster | last post by:
I keep getting the following in my output file , regardless of whether I convert endian-ness or not . How do i get "01 02 03 04" .... Mahamannu output : 04 03 02 01 b0 00 00
6
by: Javier | last post by:
Hello people, I'm recoding a library that made a few months ago, and now that I'm reading what I wrote I have some questions. My program reads black and white images from a bitmap (BMP 24bpp...
7
by: apollo135 | last post by:
Dear all, Could someone please clarify and help with byte ordering macro (big/litte endian conversion)? I found thefollowinf macron on the internet but I have a doubt to use it ... ============...
3
by: apollo135 | last post by:
Dear all, Could someone please clarify and help with byte ordering macro (big/litte endian conversion)? I found thefollowinf macron on the internet but I have a doubt to use it ... ============...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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...

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.