Any Method to Determine Endianness at Compile Time ?

P

perry.yuan

How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression"),
i.e.

#if some_expression
#define TARGET_IS_LITTLE_ENDIAN
#else
#define TARGET_IS_BIG_ENDIAN

No way or some way? TIA.
 
B

Ben Pfaff

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression")

One way this is commonly done is to build in two stages. First,
compile and run a test program that tests for the
implementation's endianness. Then use the test program's output
to configure macros to be defined while building the rest of the
program.
 
R

Richard Tobin

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time?

You can't write a compile-time expression to determine it, because
endianness is a property of representations, not values, and there
are no objects whose representations can be examined at compile
time.

One solution is to run a program at compile time that determines
the endianness and outputs a suitable #define to a file which
you then include.

-- Richard
 
E

Eric Sosman

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression"),
i.e.

#if some_expression
#define TARGET_IS_LITTLE_ENDIAN
#else
#define TARGET_IS_BIG_ENDIAN

No way or some way? TIA.

This is Question 10.16 in the comp.lang.c Frequently
Asked Questions (FAQ) list <http://www.c-faq.com/>. You've
been around this newsgroup long enough to have seen the
FAQ mentioned several dozens of times; shame on you for
not bothering to read it.
 
J

jacob navia

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression"),
i.e.

#if some_expression
#define TARGET_IS_LITTLE_ENDIAN
#else
#define TARGET_IS_BIG_ENDIAN

No way or some way? TIA.

#include <stdio.h>
int main(void)
{
union {
char c;
int i;
} u;
u.i = 0;
u.c = 1;

if (u.i == 1)
printf("little endian\n");
else
printf("big endian\n");
}

This printsd "little endian" in the intel processor,
"big endian" in the power pc. I think it should work.
 
J

jacob navia

jacob said:
#include <stdio.h>
int main(void)
{
union {
char c;
int i;
} u;
u.i = 0;
u.c = 1;

if (u.i == 1)
printf("little endian\n");
else
printf("big endian\n");
}

This printsd "little endian" in the intel processor,
"big endian" in the power pc. I think it should work.

Sorry, I missed the "preprocessor" part.
 
B

Ben Pfaff

jacob navia said:
This printsd "little endian" in the intel processor,
"big endian" in the power pc. I think it should work.

I don't think you actually read the OP's question.
 
W

Willem

jacob wrote:
) perry.yuan wrote:
)> How could I determine the endianness of my compile environment at
)> compile time, instead of run time? I need a macro ("some_expression"),
^^^^^^^ ^^^

) int main(void)
) {
) union {
) char c;
) int i;
) } u;
) u.i = 0;
) u.c = 1;
)
) if (u.i == 1)
) printf("little endian\n");
) else
) printf("big endian\n");
) }

Isn't that a run time solution ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

jacob navia

Richard said:
Not if you run it at compile time :)

-- Richard

I sent a message recognizing my error around 30 seconds
after I sent the first answer.

Again:

Excuse, it was a mistake
 
R

Richard Tobin

Willem said:
) int main(void)
) {
) union {
) char c;
) int i;
) } u;
) u.i = 0;
) u.c = 1;
)
) if (u.i == 1)
) printf("little endian\n");
) else
) printf("big endian\n");
) }
Isn't that a run time solution ?

Not if you run it at compile time :)

-- Richard
 
M

Morris Dovey

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression"),
i.e.

#if some_expression
#define TARGET_IS_LITTLE_ENDIAN
#else
#define TARGET_IS_BIG_ENDIAN

No way or some way? TIA.

Hmm. If you're willing to run another program before the compile,
you could run something like this from your compiler script or
makefile (although it need only be run once on any given target
machine):

/* Method of determining endian-ness is Jacob Navia's */
/* Adjust path and filename to suit your situation */

#include <stdio.h>
#include <stdlib.h>
int main(void)
{ FILE *fp;
union
{ char c;
int i;
} u;
u.i = 0;
u.c = 1;
if (fp = fopen("/usr/include/endian.h","w"))
{ fprintf(fp,"#define %S_ENDIAN\n",(u.i&1)?"LITTLE":"BIG");
fclose(fp);
return EXIT_SUCCESS;
}
return EXIT_FAILURE;
}

then in your application just

#include <endian.h>

#ifdef BIG_ENDIAN
/* Big endian code */
#else
/* Little endian code */
#endif
 
U

user923005

Hmm. If you're willing to run another program before the compile,
you could run something like this from your compiler script or
makefile (although it need only be run once on any given target
machine):

/* Method of determining endian-ness is Jacob Navia's */
/* Adjust path and filename to suit your situation    */

#include <stdio.h>
#include <stdlib.h>
int main(void)
{  FILE *fp;
   union
   {  char c;
      int  i;
   }  u;
   u.i = 0;
   u.c = 1;
   if (fp = fopen("/usr/include/endian.h","w"))
   {  fprintf(fp,"#define %S_ENDIAN\n",(u.i&1)?"LITTLE":"BIG");
      fclose(fp);
      return EXIT_SUCCESS;
   }
   return EXIT_FAILURE;

}

then in your application just

#include <endian.h>

#ifdef BIG_ENDIAN
   /* Big endian code */
#else
   /* Little endian code */
#endif

Of course, all of these union methods result in undefined behavior.
I think that the risk is lower if you make it an unsigned char and
assign a value to the integer and examine the unsigned char.
At any rate (from the C-FAQ):

10.16: How can I use a preprocessor #if expression to tell if a
machine is big-endian or little-endian?

A: You probably can't. (Preprocessor arithmetic uses only long
integers, and there is no concept of addressing.) Are you
sure you need to know the machine's endianness explicitly?
Usually it's better to write code which doesn't care.
See also question 20.9.

References: ISO Sec. 6.8.1; H&S Sec. 7.11.1 p. 225.

20.9: How can I determine whether a machine's byte order is
big-endian or little-endian?

A: One way is to use a pointer:

int x = 1;
if(*(char *)&x == 1)
printf("little-endian\n");
else printf("big-endian\n");

It's also possible to use a union.

See also questions 10.16 and 20.9b.

References: H&S Sec. 6.1.2 pp. 163-4.

It seems to be less of a problem to store an "X" in a union and
examine it as a "Y" with C99 than with previous iterations of the
standard, but in C89 I am pretty sure that the behavior is undefined
unless you are examining unsigned characters.


We have to compiler for dozens of platforms here. We just figure out
the endianness before hand and compile with an appropriate macro
definition.
 
R

Richard Tobin

How could I determine the endianness of my compile environment at
compile time, instead of run time?
[/QUOTE]
Read the manuals for your CPU, operating system, and compiler.

This is a stupid, unhelpful answer. The aim is obviously to produce a
system that works on systems you don't necessarily have.
But why not do the checking at run-time instead?

That is often sufficient, but is sometimes unacceptably inefficient
(or verbose, if you replicate large chunks of code). If efficiency is
important, arrange to run a program at compile time to determine the
answer.
Another method I've seen is, use a char pointer to point to the 0th
byte of an int which is set to 65. If the char pointed to is "A",
you're little endian.

Why confuse the issue by bringing in ASCII codes?

-- Richard
 
R

Robbie Hatley

perry.yuan said:
How could I determine the endianness of my compile environment at
compile time, instead of run time?

Read the manuals for your CPU, operating system, and compiler.
I need a macro

You could use a macro to do conditional compilation, yes. Your compiler
might even provide you with endian-ness macros.

But why not do the checking at run-time instead? Your code would be
more portable that way. Read Jacob Navia's reply to your post.
I'd recommend that approach.

Another method I've seen is, use a char pointer to point to the 0th
byte of an int which is set to 65. If the char pointed to is "A",
you're little endian. If it's the NUL character instead, you're
big-endian.
 
R

Richard

Robbie Hatley said:
Read the manuals for your CPU, operating system, and compiler.


You could use a macro to do conditional compilation, yes. Your compiler
might even provide you with endian-ness macros.

But why not do the checking at run-time instead? Your code would be
more portable that way. Read Jacob Navia's reply to your post.
I'd recommend that approach.

Another method I've seen is, use a char pointer to point to the 0th
byte of an int which is set to 65. If the char pointed to is "A",
you're little endian. If it's the NUL character instead, you're
big-endian.

And the reason you can't use an int or long of value 1 is?
 
M

Morris Dovey

user923005 said:
We have to compiler for dozens of platforms here. We just figure out
the endianness before hand and compile with an appropriate macro
definition.

That would be my approach, as well - but I don't generally find
myself compiling here for other platforms. My normal mode of
operation has been to code, compile, and (at least) unit test on
this (nearly ancient) machine - then recompile and test on the
target machine. Whenever a cross-compiler has been needed, it's
always been available at the client's site.

Heh - I just realized that this is the same machine I first used
to read this group. I guess that makes it a "keeper". :)
 
C

christian.bau

There is no way in Standard C. But read the manual(s) for all
compilers that you are using. Most compilers will provide the
information that you need in some form. Write a header file that
checks for all compilers that you can identify and defines the macro
that you want, and compiles a #error statement if the compiler is not
one that you can identify.
 
G

Gordon Burditt

How could I determine the endianness of my compile environment at
compile time, instead of run time? I need a macro ("some_expression"),
i.e.

#if some_expression
#define TARGET_IS_LITTLE_ENDIAN
#else
#define TARGET_IS_BIG_ENDIAN

No way or some way? TIA.

This is wrong unless sizeof(int) = 2. There are more possible byte
orders than big endian or little endian (24 for sizeof(int) = 4).

It is not permitted for an expression in a #if expression to access
memory, so you cannot directly test for endianness that way.

Your platform might provide pre-defined symbols or symbols in header
files that give you a clue. (However, that works only on platforms
that conform to the convention.) For example:

#if defined(ARCH_I386)
#define TARGET_IS_LITTLE_ENDIAN
#endif
#if defined(ARCH_IBM360)
#define TARGET_IS_BIG_ENDIAN
#endif
#if defined(ARCH_PDP11)
#define TARGET_IS_MIXED_ENDIAN
#endif
(maintaining the above list will likely be a headache)

#if !defined(TARGET_IS_LITTLE_ENDIAN) && !defined(TARGET_IS_BIG_ENDIAN) && !defined(TARGET_IS_MIXED_ENDIAN)
#define TARGET_IS_UNKNOWN_ENDIAN
#endif
 
S

srimks11

This is wrong unless sizeof(int) = 2. There are more possible byte
orders than big endian or little endian (24 for sizeof(int) = 4).

It is not permitted for an expression in a #if expression to access
memory, so you cannot directly test for endianness that way.

Your platform might provide pre-defined symbols or symbols in header
files that give you a clue. (However, that works only on platforms
that conform to the convention.) For example:

#if defined(ARCH_I386)
#define TARGET_IS_LITTLE_ENDIAN
#endif
#if defined(ARCH_IBM360)
#define TARGET_IS_BIG_ENDIAN
#endif
#if defined(ARCH_PDP11)
#define TARGET_IS_MIXED_ENDIAN
#endif
(maintaining the above list will likely be a headache)

#if !defined(TARGET_IS_LITTLE_ENDIAN) && !defined(TARGET_IS_BIG_ENDIAN) && !defined(TARGET_IS_MIXED_ENDIAN)
#define TARGET_IS_UNKNOWN_ENDIAN
#endif

--

Hi.

Probably declaring the option in MAKEFILE as a switch will take care
to compile for BIG-ENDIAN or LITTLE-ENDIAN. CISC are LE type whereas
RISC are BE type, one has to choice the option and then build which
takes care at compile time.

HIH

BR
MKS
 

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,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top