122

Is there a one line macro definition to determine the endianness of the machine? I am using the following code but converting it to macro would be too long:

unsigned char test_endian( void )
{
    int test_var = 1;
    unsigned char *test_endian = (unsigned char*)&test_var;

    return (test_endian[0] == 0);
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
manav m-n
  • 11,136
  • 23
  • 74
  • 97
  • 2
    Why not include the same code into a macro? – sharptooth Jan 20 '10 at 09:46
  • 4
    You can't portably determine endianness with the C preprocessor alone. You also want `0` instead of `NULL` in your final test, and change one of the `test_endian` objects to something else :-). – Alok Singhal Jan 20 '10 at 09:48
  • Why do you need a macro? – Daniel Daranas Jan 20 '10 at 09:48
  • 2
    Also why is a macro necessary? Inline function would do the same and is much safer. – sharptooth Jan 20 '10 at 09:49
  • Is this a puzzle/homework assignment? Normally you shouldn't actually need to worry about the endianness of your platform. – jamesdlin Jan 20 '10 at 10:12
  • 16
    @Sharptooth, a macro is appealing because its value may be known at compile time, meaning you could use your platform's endianness to control template instantiation, for example, or maybe even select different blocks of code with an `#if` directive. – Rob Kennedy Apr 08 '10 at 05:08
  • 1
    @jamesdlin When writing a network application or an application which exports binary data into a file, knowing the endianness and properly handling conversions is critical. For example if a Sun SPARC (big endian) server and an Intel x86 (little endian) server swap binary data, one of the two will need to convert the data the data will be misinterpreted. You could use `ntohl()`, `htonl()`, `ntohs()`, or `htons()`, but they only handle 32bit and 16bit data types. – David M. Syzdek May 15 '14 at 00:04
  • 1
    @DavidM.Syzdek The data format on the *wire* must be in a known, *specified* format (usually network order). You do *not* need to know the endianness of your platform to write to that specific format; you can write endian-*agnostic* code by writing one byte at a time (e.g. `fputc((value >> 24) & 0xFF, fp), fputc((value >> 16) & 0xFF, fp)` ...) – jamesdlin May 15 '14 at 00:30
  • 4
    That's true, but inefficient. If I have a little-endian cpu, and I'm writing little-endian data to the wire or to a file, I'd much rather avoid unpacking and repacking data to no purpose. I used to write video drivers for a living. It is *extremely* important when writing pixels to a video card to optimize every place you can. – Edward Falk Sep 05 '16 at 16:26

24 Answers24

114

Code supporting arbitrary byte orders, ready to be put into a file called order32.h:

#ifndef ORDER32_H
#define ORDER32_H

#include <limits.h>
#include <stdint.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

enum
{
    O32_LITTLE_ENDIAN = 0x03020100ul,
    O32_BIG_ENDIAN = 0x00010203ul,
    O32_PDP_ENDIAN = 0x01000302ul,      /* DEC PDP-11 (aka ENDIAN_LITTLE_WORD) */
    O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 (aka ENDIAN_BIG_WORD) */
};

static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
    { { 0, 1, 2, 3 } };

#define O32_HOST_ORDER (o32_host_order.value)

#endif

You would check for little endian systems via

O32_HOST_ORDER == O32_LITTLE_ENDIAN
Alexander Stohr
  • 159
  • 1
  • 18
Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 14
    This doesn't let you *decide* endian-ness until runtime though. The following fails to compile because. /** isLittleEndian::result --> 0 or 1 */ struct isLittleEndian { enum isLittleEndianResult { result = (O32_HOST_ORDER == O32_LITTLE_ENDIAN) }; }; – user48956 Aug 13 '10 at 17:54
  • 4
    Is it imposiible to get result until runtime? – k06a Dec 26 '10 at 12:03
  • 9
    Why `char`? Better use `uint8_t` and fail if this type isn't available (which can be checked by `#if UINT8_MAX`). Note that `CHAR_BIT` is independent from `uint8_t`. – Andreas Spindler Oct 31 '12 at 11:33
  • Why `4` in `bytes[4]`? If code is to be compiled on various platforms, why use this assumption? Better to use `sizeof(some_integer)` to drive `char` array size. – chux - Reinstate Monica Apr 14 '15 at 13:28
  • 2
    This is UB in c++: https://stackoverflow.com/questions/11373203/accessing-inactive-union-member-undefined-behavior?lq=1 –  Jul 01 '16 at 08:55
  • 4
    Let me toss one more into the mix, for completeness: `O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */` – Edward Falk Sep 05 '16 at 17:10
  • That's from this excellent essay I found on the subject: https://sourceforge.net/p/predef/wiki/Endianness/ – Edward Falk Sep 05 '16 at 17:11
  • 1
    ... and can you use this with #if? no. this is no more or less useful than make a function or variables, where as a true macro has wider utility (e.g. to guard an #error directive) – jheriko Jan 05 '17 at 09:39
  • 2
    See https://port70.net/~nsz/c/c11/n1570.html#6.2.6.1p7. This macro is not portable and relies on unspecified behavior in the C language spec. Though this probably works on many systems, it's not technically portable. – jwdonahue Sep 19 '18 at 21:02
  • 1
    @AndreasSpindler Are you sure? While it’s true that `uint8_t` does not have to be _the same type_ as `unsigned char` (so a DeathStation might _e.g._ store their bits in opposite order), it seems to me that `uint8_t` present implies `CHAR_BIT == 8` and the sets of valid (non-trap) in-memory representations of `unsigned char` and `uint8_t` coinciding, because: (1) `unsigned char` is the smallest type; (2) `unsigned char` has no padding bits, (3) `UCHAR_MAX` must be at least 255 and `CHAR_BIT` at least 8, (4) `uint8_t`, wherever present, must be an integer type with no padding and maximum 255. – Alex Shpilkin Jul 30 '21 at 16:51
56

If you have a compiler that supports C99 compound literals:

#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1})

or:

#define IS_BIG_ENDIAN (!(union { uint16_t u16; unsigned char c; }){ .u16 = 1 }.c)

In general though, you should try to write code that does not depend on the endianness of the host platform.


Example of host-endianness-independent implementation of ntohl():

uint32_t ntohl(uint32_t n)
{
    unsigned char *np = (unsigned char *)&n;

    return ((uint32_t)np[0] << 24) |
        ((uint32_t)np[1] << 16) |
        ((uint32_t)np[2] << 8) |
        (uint32_t)np[3];
}
caf
  • 233,326
  • 40
  • 323
  • 462
  • couldn't this be optimized using the terminator? :) –  Jan 20 '10 at 12:01
  • 4
    "you should try to write code that does not depend on the endianness of the host platform". Unfortunately my plea, "I know we're writing a POSIX compatibility layer, but I don't want to implement ntoh, because it depends on the endianness of the host platform" always fell on deaf ears ;-). Graphics format handling and conversion code is the other main candidate I've seen - you don't want to base everything off calling ntohl all the time. – Steve Jessop Jan 20 '10 at 13:03
  • 8
    You can implement `ntohl` in a way that does not depend on the endianness of the host platform. – caf Jan 20 '10 at 13:13
  • Not efficiently. At least, not with the compilers we had at the time (GCCE and a bunch of others). They tended to do something in the case where the platform was big-endian. – Steve Jessop Jan 20 '10 at 13:15
  • 1
    @caf how would you write ntohl in an host-endianness-independent way? – Hayri Uğur Koltuk Mar 01 '12 at 12:39
  • 5
    @AliVeli: I've added an example implementation to the answer. – caf Mar 01 '12 at 21:12
  • Hmmm; I kind of like that implementation. It's simple, but not optimized for the case where the host is also big-endian. – Edward Falk Jul 11 '12 at 20:25
  • 6
    I should also add for the record, that "(*(uint16_t *)"\0\xff" < 0x100)" won't compile into a constant, no matter how much I optimize, at least with gcc 4.5.2. It always creates executable code. – Edward Falk Jul 11 '12 at 20:29
  • Simple and effective, I like it. – Qiang Xu Oct 11 '12 at 19:00
  • 1
    The `IS_BIG_ENDIAN` code depends on string literals being aligned to 16 bit boundaries or the platform supporting misaligned access to 16 bit quantities. This is not an entirely portable assumption (notably on ARM based platforms). – microtherion Nov 11 '13 at 13:08
  • 1
    @microtherion: Right. My original suggestion was supposed to be a little tongue-in-cheek but since people apparently found it useful, I've added versions using C99 compound literals that don't have that problem. – caf Nov 12 '13 at 03:13
  • The only problem with this is that it doesn't work for cross compiling. – MarcusJ Aug 16 '17 at 01:30
  • 1
    @MarcusJ: How so? It will report the endian-ness of the target that runs the binary (the downside being that it can't be used as a compile-time constant and relies on the optimiser to remove any runtime overhead). – caf Aug 16 '17 at 04:12
  • Oh, I was under the impression it checked at compile time, but of the host environment, not the target one. that's even worse, I've already got a runtime detection function; what I really want tho is a compile time one. – MarcusJ Aug 16 '17 at 11:25
52

There is no standard, but on many systems including <endian.h> will give you some defines to look for.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 42
    Test the endianness with `#if __BYTE_ORDER == __LITTLE_ENDIAN` and `#elif __BYTE_ORDER == __BIG_ENDIAN`. And generate an `#error` elsewise. – To1ne May 04 '11 at 07:43
  • 7
    `` is not available on Windows – rustyx Nov 02 '16 at 15:27
  • 2
    [Android](https://android.googlesource.com/platform/system/core/+/master/include/utils/Endian.h) and [Chromium](https://chromium.googlesource.com/aosp/platform/system/core/+/master/include/utils/Endian.h) projects use [`endian.h`](https://linux.die.net/include/endian.h) unless [`__APPLE__`](https://gcc.gnu.org/onlinedocs/cpp/System-specific-Predefined-Macros.html#System-specific-Predefined-Macros) or [`_WIN32`](https://gcc.gnu.org/onlinedocs/cpp/System-specific-Predefined-Macros.html#System-specific-Predefined-Macros) is defined. – patryk.beza Nov 11 '16 at 13:42
  • 1
    In OpenBSD 6.3, provides `#if BYTE_ORDER == LITTLE_ENDIAN`(or `BIG_ENDIAN`) with no underscores before the names. `_BYTE_ORDER` is only for system headers. `__BYTE_ORDER` does not exist. – George Koehler Apr 06 '18 at 04:11
  • 3
    @To1ne I doubt that Endianness is relevant for Windows, as Windows (at least currently) runs only on x86 and ARM machines. x86 always being LE and ARM being configurable to use either architecture. – SimonC Dec 19 '18 at 08:13
  • On MacOs 10.15.4 (Catalina) it is in . – Craig S. Anderson Jun 03 '20 at 22:33
  • Here is an example usage in redis - https://github.com/redis/redis/blob/c2f1815bcbf5a02ae3920c2efa31099226a966bb/src/config.h#L233-L237 – srgsanky Jun 04 '23 at 17:53
29

To detect endianness at run time, you have to be able to refer to memory. If you stick to standard C, declarating a variable in memory requires a statement, but returning a value requires an expression. I don't know how to do this in a single macro—this is why gcc has extensions :-)

If you're willing to have a .h file, you can define

static uint32_t endianness = 0xdeadbeef; 
enum endianness { BIG, LITTLE };

#define ENDIANNESS ( *(const char *)&endianness == 0xef ? LITTLE \
                   : *(const char *)&endianness == 0xde ? BIG \
                   : assert(0))

and then you can use the ENDIANNESS macro as you will.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • 6
    I like this because it acknowledges the existence of endianness other than little and big. – Alok Singhal Jan 20 '10 at 09:58
  • 9
    Speaking of which, it might be worth calling the macro INT_ENDIANNESS, or even UINT32_T_ENDIANNESS, since it only tests the storage representation of one type. There's an ARM ABI where integral types are little-endian, but doubles are middle-endian (each word is little-endian, but the word with the sign bit in it comes before the other word). That caused some excitement among the compiler team for a day or so, I can tell you. – Steve Jessop Jan 20 '10 at 12:56
19

If you want to only rely on the preprocessor, you have to figure out the list of predefined symbols. Preprocessor arithmetics has no concept of addressing.

GCC on Mac defines __LITTLE_ENDIAN__ or __BIG_ENDIAN__

$ gcc -E -dM - < /dev/null |grep ENDIAN
#define __LITTLE_ENDIAN__ 1

Then, you can add more preprocessor conditional directives based on platform detection like #ifdef _WIN32 etc.

Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
  • 6
    GCC 4.1.2 on Linux doesn't appear to define those macros, although GCC 4.0.1 and 4.2.1 define them on Macintosh. So it's not a reliable method for cross-platform development, even when you're allowed to dictate which compiler to use. – Rob Kennedy Apr 08 '10 at 03:02
  • 1
    oh yeah it's because it's only defined by GCC on Mac. – Gregory Pakosz Aug 08 '11 at 02:18
  • Note: My GCC (on Mac) defines `#define __BIG_ENDIAN__ 1` and `#define _BIG_ENDIAN 1`. –  Sep 28 '14 at 16:16
  • clang 5.0.1 for OpenBSD/amd64 has `#define __LITTLE_ENDIAN__ 1`. This macro seems to be a clang feature, not a gcc feature. The `gcc` command in some Macs isn't gcc, it's clang. – George Koehler Apr 06 '18 at 04:05
  • GCC 4.2.1 on Mac was GCC back then – Gregory Pakosz Apr 06 '18 at 11:30
17

I believe this is what was asked for. I only tested this on a little endian machine under msvc. Someone plese confirm on a big endian machine.

    #define LITTLE_ENDIAN 0x41424344UL 
    #define BIG_ENDIAN    0x44434241UL
    #define PDP_ENDIAN    0x42414443UL
    #define ENDIAN_ORDER  ('ABCD') 

    #if ENDIAN_ORDER==LITTLE_ENDIAN
        #error "machine is little endian"
    #elif ENDIAN_ORDER==BIG_ENDIAN
        #error "machine is big endian"
    #elif ENDIAN_ORDER==PDP_ENDIAN
        #error "jeez, machine is PDP!"
    #else
        #error "What kind of hardware is this?!"
    #endif

As a side note (compiler specific), with an aggressive compiler you can use "dead code elimination" optimization to achieve the same effect as a compile time #if like so:

    unsigned yourOwnEndianSpecific_htonl(unsigned n)
    {
        static unsigned long signature= 0x01020304UL; 
        if (1 == (unsigned char&)signature) // big endian
            return n;
        if (2 == (unsigned char&)signature) // the PDP style
        {
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        if (4 == (unsigned char&)signature) // little endian
        {
            n = (n << 16) | (n >> 16);
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        // only weird machines get here
        return n; // ?
    }

The above relies on the fact that the compiler recognizes the constant values at compile time, entirely removes the code within if (false) { ... } and replaces code like if (true) { foo(); } with foo(); The worst case scenario: the compiler does not do the optimization, you still get correct code but a bit slower.

ggpp23
  • 179
  • 1
  • 2
  • I like this method, but correct me if I'm wrong: this only works when you're compiling on the machine you're building for, correct? – leetNightshade Mar 31 '12 at 19:24
  • 3
    gcc also throws an error due to multi-character character constants. Thus, not portable. – Edward Falk Jul 11 '12 at 20:34
  • 3
    what compiler is letting you write `'ABCD'` ? – Ryan Haining Aug 19 '14 at 20:19
  • 2
    Many compilers will allow multibyte character constants in relaxed compliance modes, but run the top part with `clang -Wpedantic -Werror -Wall -ansi foo.c` and it will error. (Clang and this specifically: `-Wfour-char-constants -Werror`) –  Dec 03 '14 at 20:25
  • @Edward Falk It is **not an error** to have a multi-character constant in code. It is implementation-defined behavior C11 6.4.4.4. 10. gcc and other may/may not warn/error depending on settings, but it is not a C error. It certainly is not popular to use multi-character character constants. – chux - Reinstate Monica Mar 02 '16 at 22:16
13

If you are looking for a compile time test and you are using gcc, you can do:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

See gcc documentation for more information.

Jérôme Pouiller
  • 9,249
  • 5
  • 39
  • 47
11

You can in fact access the memory of a temporary object by using a compound literal (C99):

#define IS_LITTLE_ENDIAN (1 == *(unsigned char *)&(const int){1})

Which GCC will evaluate at compile time.

u0b34a0f6ae
  • 48,117
  • 14
  • 92
  • 101
7

The 'C network library' offers functions to handle endian'ness. Namely htons(), htonl(), ntohs() and ntohl() ...where n is "network" (ie. big-endian) and h is "host" (ie. the endian'ness of the machine running the code).

These apparent 'functions' are (commonly) defined as macros [see <netinet/in.h>], so there is no runtime overhead for using them.

The following macros use these 'functions' to evaluate endian'ness.

#include <arpa/inet.h>
#define  IS_BIG_ENDIAN     (1 == htons(1))
#define  IS_LITTLE_ENDIAN  (!IS_BIG_ENDIAN)

In addition:

The only time I ever need to know the endian'ness of a system is when I write-out a variable [to a file/other] which may be read-in by another system of unknown endian'ness (for cross-platform compatability) ...In cases such as these, you may prefer to use the endian functions directly:

#include <arpa/inet.h>

#define JPEG_MAGIC  (('J'<<24) | ('F'<<16) | ('I'<<8) | 'F')

// Result will be in 'host' byte-order
unsigned long  jpeg_magic = JPEG_MAGIC;

// Result will be in 'network' byte-order (IE. Big-Endian/Human-Readable)
unsigned long  jpeg_magic = htonl(JPEG_MAGIC);
ugoren
  • 16,023
  • 3
  • 35
  • 65
BlueChip
  • 143
  • 2
  • 13
  • This doesn't really answer the question which was looking for a quick way to determine endianness. – Oren Jun 12 '13 at 00:50
  • @Oren : With respect to your valid criticism, I have prepended detail which addresses the original question more directly. – BlueChip Jun 13 '13 at 06:09
7

If you dump the preprocessor #defines

gcc -dM -E - < /dev/null
g++ -dM -E -x c++ - < /dev/null

You can usually find stuff that will help you. With compile time logic.

#define __LITTLE_ENDIAN__ 1
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__

Various compilers may have different defines however.

Sam P
  • 681
  • 5
  • 19
6

Use an inline function rather than a macro. Besides, you need to store something in memory which is a not-so-nice side effect of a macro.

You could convert it to a short macro using a static or global variable, like this:

static int s_endianess = 0;
#define ENDIANESS() ((s_endianess = 1), (*(unsigned char*) &s_endianess) == 0)
user231967
  • 1,935
  • 11
  • 9
5

Whilst there is no portable #define or something to rely upon, platforms do provide standard functions for converting to and from your 'host' endian.

Generally, you do storage - to disk, or network - using 'network endian', which is BIG endian, and local computation using host endian (which on x86 is LITTLE endian). You use htons() and ntohs() and friends to convert between the two.

Will
  • 73,905
  • 40
  • 169
  • 246
4

Don't forget that endianness is not the whole story - the size of char might not be 8 bits (e.g. DSP's), two's complement negation is not guaranteed (e.g. Cray), strict alignment might be required (e.g. SPARC, also ARM springs into middle-endian when unaligned), etc, etc.

It might be a better idea to target a specific CPU architecture instead.

For example:

#if defined(__i386__) || defined(_M_IX86) || defined(_M_IX64)
  #define USE_LITTLE_ENDIAN_IMPL
#endif

void my_func()
{
#ifdef USE_LITTLE_ENDIAN_IMPL
  // Intel x86-optimized, LE implementation
#else
  // slow but safe implementation
#endif
}

Note that this solution is also not ultra-portable unfortunately, as it depends on compiler-specific definitions (there is no standard, but here's a nice compilation of such definitions).

rustyx
  • 80,671
  • 25
  • 200
  • 267
4
#include <stdint.h>
#define IS_LITTLE_ENDIAN (*(uint16_t*)"\0\1">>8)
#define IS_BIG_ENDIAN (*(uint16_t*)"\1\0">>8)
  • 6
    This also generates executable code, not a constant. You couldn't do "#if IS_BIG_ENDIAN" – Edward Falk Jul 11 '12 at 20:32
  • 1
    I like this solution since it doesn't rely on C/C++ standards undefined behavior, as far as I understand. It's not compile time but the only standard solution for that is waiting for c++20 [std::endian](https://en.cppreference.com/w/cpp/types/endian) – ceztko Apr 13 '20 at 10:36
3

Try this:

#include<stdio.h>        
int x=1;
#define TEST (*(char*)&(x)==1)?printf("little endian"):printf("Big endian")
int main()
{

   TEST;
}
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
2

Please pay attention that most of the answers here are not portable, since compilers today will evaluate those answers in compilation time (depends on the optimization) and return a specific value based on a specific endianness, while the actual machine endianness can differ. The values on which the endianness is tested, won't never reach the system memory thus the real executed code will return the same result regardless of the actual endianness.

For example, in ARM Cortex-M3 the implemented endianness will reflect in a status bit AIRCR.ENDIANNESS and compiler cannot know this value in compile time.

Compilation output for some of the answers suggested here:

https://godbolt.org/z/GJGNE2 for this answer,

https://godbolt.org/z/Yv-pyJ for this answer, and so on.

To solve it you will need to use the volatile qualifier. Yogeesh H T's answer is the closest one for today's real life usage, but since Christoph suggests more comprehensive solution, a slight fix to his answer would make the answer complete, just add volatile to the union declaration: static const volatile union.

This would assure storing and reading from memory, which is needed to determine endianness.

izac89
  • 3,790
  • 7
  • 30
  • 46
2

This question is actual for cpp too, so I asked here.

ONLY #if __cplusplus > 201703L

#include <bit>
#include <iostream>

using namespace std;

int main()
{
    if constexpr (endian::native == endian::big)
        cout << "big-endian";
    else if constexpr (endian::native == endian::little)
        cout << "little-endian";
    else
        cout << "mixed-endian";
}

For more info: https://en.cppreference.com/w/cpp/types/endian

cheiser
  • 126
  • 1
  • 10
  • Thanks for this. Nice to see a sensible feature in C++. If only you hadn't kneecapped your own answer with the `using namespace std` thing. – Roflcopter4 Nov 04 '22 at 19:22
1

If your compiler supports compound literals and you are pointedly not using C++ you can use

#define BIG_ENDIAN      ((*(const char*)&(const int){0x01020304}) == 0x01)
#define LITTLE_ENDIAN   ((*(const char*)&(const int){0x01020304}) == 0x04)

This doesn't require the declaration of any runtime variables, which I think makes it a good deal cleaner than most of the other solutions

Willis Hershey
  • 1,520
  • 4
  • 22
  • but it's runtime and not compile time, which means the expression will be evaluated many times in the program's lifetime and may be inefficient – phuclv Mar 18 '22 at 16:13
1

In C++20 an enum std::endian in the header <bit> was introduced:

https://en.cppreference.com/w/cpp/types/endian

#include <bit>
#include <iostream>
 
int main() {
 
    if constexpr (std::endian::native == std::endian::big)
        std::cout << "big-endian\n";
    else if constexpr (std::endian::native == std::endian::little)
        std::cout << "little-endian\n";
    else std::cout << "mixed-endian\n";
}
Spille
  • 527
  • 4
  • 12
0

If boost is available then you can use Boost.Predef which contains various predefined macros for the target platform including endianness (BOOST_ENDIAN_*). Yes boost is often thought as a C++ library, but this one is a preprocessor header that works with C as well! It allows you to detect endian in compile time portably

This library defines a set of compiler, architecture, operating system, library, and other version numbers from the information it can gather of C, C++, Objective C, and Objective C++ predefined macros or those defined in generally available headers. The idea for this library grew out of a proposal to extend the Boost Config library to provide more, and consistent, information than the feature definitions it supports. What follows is an edited version of that brief proposal.

For example

#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/other/endian.h>

#if   BOOST_ENDIAN_BIG_BYTE
#elif BOOST_ENDIAN_LITTLE_BYTE
#elif BOOST_ENDIAN_LITTLE_WORD
...
#endif

More details can be found in BOOST_ENDIAN_* section

Demo on Godbolt


Note that it obviously can't detect bi-endian platforms where the endian can be changed during runtime

The detection is conservative in that it only identifies endianness that it knows for certain. In particular bi-endianness is not indicated as is it not practically possible to determine the endianness from anything but an operating system provided header. And the currently known headers do not define that programatic bi-endianness is available.

phuclv
  • 37,963
  • 15
  • 156
  • 475
0
#include <stdio.h>

#define CHECK_FOR_ENDIANNESS (*(char*)&(unsigned int){1})

int main() {
    if (CHECK_FOR_ENDIANNESS) {
        printf("little-endian.\n");
    } else {
        printf("big-endian.\n");
    }
    return 0;
}

How It Works

Step #1  Create an unsigned int with a value of 1
                +----------+----------+----------+----------+
Memory Address  |  0x1000  |  0x1001  |  0x1002  |  0x1003  |
                +----------+----------+----------+----------+
Little:         |  01      |  00      |  00      |  00      |
                +----------+----------+----------+----------+
Big:            |  00      |  00      |  00      |  01      |
                +----------+----------+----------+----------+

Step #2  Cast the address to a char pointer (focuses on first byte)
                +----------+
Memory Address  |  0x1000  |
                +----------+
Little:         |  01      |
                +----------+
Big:            |  00      |
                +----------+

Step #3  Dereference the char pointer to get the value

Little:         Returns 1 (for little-endian)
Big:            Returns 0 (for big-endian)

Demo

vengy
  • 1,548
  • 10
  • 18
-1

My answer is not as asked but It is really simple to find if your system is little endian or big endian?

Code:

#include<stdio.h>

int main()
{
  int a = 1;
  char *b;

  b = (char *)&a;
  if (*b)
    printf("Little Endian\n");
  else
    printf("Big Endian\n");
}
roottraveller
  • 7,942
  • 7
  • 60
  • 65
-1

C Code for checking whether a system is little-endian or big-indian.

int i = 7;
char* pc = (char*)(&i);
if (pc[0] == '\x7') // aliasing through char is ok
    puts("This system is little-endian");
else
    puts("This system is big-endian");
smamran
  • 741
  • 2
  • 14
  • 20
-4

Macro to find endiannes

#define ENDIANNES() ((1 && 1 == 0) ? printf("Big-Endian"):printf("Little-Endian"))

or

#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;
}
Yogeesh H T
  • 2,777
  • 21
  • 18
  • 3
    The first macro is incorrect and will always return "Big-Endian". Bit shifting is not affected by endianness - endianness only affect reads and stores to the memory. – GaspardP Jan 28 '16 at 16:58