2

I'm curious if this function will determine endianness.

The test is a bitmask that equals 1 if the integer someInt is stored in little endian.

in the bitmask, would 0x1000 be converted to match the endian style of the machine or would it be "constant"?

#include <stdio.h>

int isBigEndian(){
    int someInt =0x0001;
    if(someInt & 0x0100 == 1) 
        return 1;
    else 
        return 0;
}

int main(){
    int returnVal = isBigEndian();
    printf("return val is %d", returnVal);
}
Jesse
  • 1,673
  • 1
  • 16
  • 22

5 Answers5

6

That function will always return zero since your constants are stored in native endianness of the system as well. A much better bet is to just use an system API that answers your question. If you had to be portable, you can probably compare val == ntohl(val) to decide endianness.

yan
  • 20,644
  • 3
  • 38
  • 48
4

What I'd use is this:

union {
    short s;
    char b[2];
} endian;

endian.s = 1;
little_endian = endian.b[0] == 1;
MRAB
  • 20,356
  • 6
  • 40
  • 33
2

Strictly speaking, the only method that is completely ANSI C compliant would be to iterate over all possible int values and check that they all match the representation you want. However, if you can assume that all systems you'll be on are either little endian, big endian, or mixed endian (ie, nothing really weird like gray coding or BCD), you can just do something like this:

static const unsigned int testvec = 0x01020304;
static const unsigned char letest[4] = { 0x04, 0x03, 0x02, 0x01 };
static const unsigned char betest[4] = { 0x01, 0x02, 0x03, 0x04 };

int isle() {
  return !memcmp(&testvec, letest, 4);
}

int isbe() {
  return !memcmp(&testvec, betest, 4);
}

Note that if you do not look at the byte representation (ie, if you do not cast pointers to look at the raw bytes), you cannot tell what byte order is in use. 0x0001 & 0x1000 is 0 on all C implementations, because both 0x0001 and 0x1000 are equally byte-swapped (and because the little endian representation of 0x0001 is 01 00, not 10 00).

bdonlan
  • 224,562
  • 31
  • 268
  • 324
1

Better is to convert a int value to a char of sizeof(int) elements. Look at it to see what it looks like.

Also, your code relies on a very specific sizeof(int). You shouldn't do that.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int a = 0xabcdef42;
    unsigned int i;
    char *s = calloc(sizeof(a) + 1, sizeof(s[0]));
    memcpy(s, &a, sizeof(a));
    printf("%x\n", a);
    for (i = 0; i < sizeof(a); i++)
        printf("%x ", (unsigned char)s[i]);
    printf("\n");
    free(s);
    return 0;
}

Which results in (my machine has an Intel CPU)

abcdef42
42 ef cd ab 

While printing the char, make sure to convert it to unsigned, otherwise you'll see funny ffffffef values caused by sign extension.

Mihai Maruseac
  • 20,967
  • 7
  • 57
  • 109
1

This question has some really nice answers(although it's in the context of C++ and C99); also check out the comments, they are very insightful.

On Linux/Unix or anything that uses glibc(mingw/cygwin) you also have the endian.h header file with macros readily available. You could also check out the boost implementation, which is cross platform, for tips on implementing that by yourself if wanted.

Community
  • 1
  • 1
celavek
  • 5,575
  • 6
  • 41
  • 69