C program to check little vs. big endian

184,062

Solution 1

In short, yes.

Suppose we are on a 32-bit machine.

If it is little endian, the x in the memory will be something like:

       higher memory
          ----->
    +----+----+----+----+
    |0x01|0x00|0x00|0x00|
    +----+----+----+----+
    A
    |
   &x

so (char*)(&x) == 1, and *y+48 == '1'. (48 is the ascii code of '0')

If it is big endian, it will be:

    +----+----+----+----+
    |0x00|0x00|0x00|0x01|
    +----+----+----+----+
    A
    |
   &x

so this one will be '0'.

Solution 2

The following will do.

unsigned int x = 1;
printf ("%d", (int) (((char *)&x)[0]));

And setting &x to char * will enable you to access the individual bytes of the integer, and the ordering of bytes will depend on the endianness of the system.

Solution 3

This is big endian test from a configure script:

#include <inttypes.h>
int main(int argc, char ** argv){
    volatile uint32_t i=0x01234567;
    // return 0 for big endian, 1 for little endian.
    return (*((uint8_t*)(&i))) == 0x67;
}

Solution 4

Thought I knew I had read about that in the standard; but can't find it. Keeps looking. Old; answering heading; not Q-tex ;P:


The following program would determine that:

#include <stdio.h>
#include <stdint.h>

int is_big_endian(void)
{
    union {
        uint32_t i;
        char c[4];
    } e = { 0x01000000 };

    return e.c[0];
}

int main(void)
{
    printf("System is %s-endian.\n",
        is_big_endian() ? "big" : "little");

    return 0;
}

You also have this approach; from Quake II:

byte    swaptest[2] = {1,0};
if ( *(short *)swaptest == 1) {
    bigendien = false;

And !is_big_endian() is not 100% to be little as it can be mixed/middle.

Believe this can be checked using same approach only change value from 0x01000000 to i.e. 0x01020304 giving:

switch(e.c[0]) {
case 0x01: BIG
case 0x02: MIX
default: LITTLE

But not entirely sure about that one ...

Share:
184,062

Related videos on Youtube

ordinary
Author by

ordinary

sponge

Updated on July 08, 2022

Comments

  • ordinary
    ordinary almost 2 years

    Possible Duplicate:
    C Macro definition to determine big endian or little endian machine?

    int main()
    {
      int x = 1;
    
      char *y = (char*)&x;
    
      printf("%c\n",*y+48);
    }
    

    If it's little endian it will print 1. If it's big endian it will print 0. Is that correct? Or will setting a char* to int x always point to the least significant bit, regardless of endianness?

    • Sergey Kalinichenko
      Sergey Kalinichenko over 11 years
      See this answer, it may be related.
    • Bo Persson
      Bo Persson over 11 years
      @ordinary - Just a note that big endian and little endian are not the only options, that not all data types need to have the same endianness, and that some hardware can be configured at runtime. If you really need to check this, you might have to check more things.
    • mucaho
      mucaho almost 9 years
      If you have the option, consider bitwise operations on fixed width datatypes to extract/set bits. They are portable according to this answer
    • Eric
      Eric about 4 years
      Great endianness demo code for userland and even a kernel module: gitlab.com/eric.saintetienne/endianness
    • young_souvlaki
      young_souvlaki almost 4 years
      Why use ASCII. Use '0'. Why print as a char and not an int. Why start as an int.
    • young_souvlaki
      young_souvlaki almost 4 years
      To answer part of my question, print as char so C only reads a byte of data. Start as int so that we have multiple bytes and can inspect endianness. Cast to char now seems unnecessary, just print as char.
  • Nate-Wilkins
    Nate-Wilkins over 11 years
    aren't you forgetting ==1 after e.c[0]
  • user1668559
    user1668559 over 11 years
    @Nate: 1 == 1, 1 != 0, !!1 or 1 is the same. Or am I missing something here?
  • Nate-Wilkins
    Nate-Wilkins over 11 years
    Hmm not sure... This isn't my forte. I saw a similar operation but it had the ==1 at the end. So I'm not sure.
  • user1668559
    user1668559 over 11 years
    @Nate: Yes. Probably using something like e = { 0x01020304 }; Then a.c[0] == 1 would be needed as a.c[0] would be 1 or 4 on big- vs little.
  • Nate-Wilkins
    Nate-Wilkins over 11 years
    Ah yea that would be it.
  • Abin Mathew Abraham
    Abin Mathew Abraham over 8 years
    What is the significance of the value 48 added to y?
  • Marcus
    Marcus about 8 years
    @AbinMathewAbraham 48 is the ascii code of '0' :)
  • code4j
    code4j about 8 years
    I am using MAC OS with intel processors. It is supposed to be Little Endian. However, 1 seems to be a special case because when 1 is stored inside the memory, it is in big endian.
  • kadina
    kadina almost 8 years
    No need to declare as unsigned int. signed int also will do because 1 is positive and even if one bit is reserved for sign, it will be 0 anyway for positive numbers.
  • yano
    yano over 6 years
    @code4j That doesn't make any sense. The CPU architecture isn't going to make an exception simply for a specific value. What you are seeing must be a one byte value, in which case endianess makes no difference. To do an endianess test, you must choose a multi-byte value. Intel chips (AFAIK) are little endian.
  • J...S
    J...S over 5 years
    Can you tell me why we can't just use (char)x == 1 ? Why do we have to get the address, convert it to a char pointer and then dereference? Won't this be implicitly done (char)x is used?
  • luizfls
    luizfls over 4 years
    @J...S I believe (char)x would work regardless of endianness. And by "work", I mean it would assign the value 1 to x, so it wouldn't be possible to detect the endianness this way.
  • LIU Qingyuan
    LIU Qingyuan over 3 years
    Why volatile instead of const?
  • admiring_shannon
    admiring_shannon over 3 years
    I think it is an easy way to avoid any undesired compiler optimization, and actually look at the data in the ram cell to determine the answer.
  • LIU Qingyuan
    LIU Qingyuan over 3 years
    thx, optimization must be suppressed here.
  • ryyker
    ryyker over 2 years
    regarding your response: "48 is the ascii code of '0'". Would it not be useful to update your answer to "so" (char*)(&x) == 1, and *y+'0' == '1' ? (nice answer regardless, +1)