0
votes

My code is supposed to detect whether the integers stored in my array are in big endian or little endian order.

Here's my code:

#include <iostream>

using namespace std;

int main()
{
    int num[] = {0,0,0x04030201,0,0};

    //int num = 0x04030201;

    for (int i=0;i<5;i++) {
        if(*(char *)&num[i] == 1) {
            printf("\nLittle-Endian\n");
        }
        else {
            printf("Big-Endian\n");
        }
    }
    return 0;
}

Since my computer is intel, all the numbers should be stored in little endian. This means I expect the code to go through each integer in my array and print little endian, so it should just print little endian 5 times. But this is the output that I am currently getting:

Big-Endian
Big-Endian

How can I fix this?

1
Only one of your array elements has 1 as the least-significant byte of the value. The all-zero bytes of (int)0will of course not be == 1. - Peter Cordes
Also, printf is defined in <stdio.h> or <cstdio>, not <iostream> - Peter Cordes
@PeterCordes So would I fix the conditional for my if statement in that case such that the 0 can be detected as little endian? How would you solve this? - T0ny50pr4n0
Unless you already know the expected value of each element, the problem is insoluble. - user207421

1 Answers

2
votes

You can't test the endianness of arbitrary or unknown values. If all the bytes of an int are zero, it doesn't matter what order they're in.


Your code prints

Big-Endian
Big-Endian

Little-Endian
Big-Endian
Big-Endian

as expected on my x86-64 system, because your testing method is wrong. Your question makes it sound like it always printed Big-Endian!


Only one of your array elements has 1 as the least-significant byte of the value. The all-zero bytes of (int)0 will of course not be == 1.

You can't check endianness with a number where all the bytes have the same value, because regardless of endianness you'll load the same value.

The == 1 check works for 0x04030201 because the low byte of that value is 1. It doesn't work in general. You could equally do something like == 0x88 in 0x4455667788 to see if the first byte in memory is the 0x88 byte.

(I'm saying "byte" instead of char because we're talking about x86-64, which does have 8-bit bytes, and all the mainstream C++ implementations use 1-byte char and 32-bit int.)


How to fix it

Endianness is a property of the implementation for a certain target architecture, and can't be different for different array elements.

int  endian_test = 0x12345678;
char *p = (char*)&endian_test;

const char *endian_string = "unknown endian";
if (p[0] == 0x78 && p[1] == 0x56 && p[2] == 0x34 && p[3] = 0x12)
    endian_string = "Little-Endian";
if (p[3] == 0x78 && p[2] == 0x56 && p[1] == 0x34 && p[0] = 0x12)
    endian_string = "Big-Endian";
// test for PDP-endian if you want

for (int i=0;i<5;i++) {
    // It's guaranteed that all elements of the array have the same endianness as endian_test
    puts(endian_string);
}

Big and little aren't the only endiannesses possible.

Also note that you can and detect this with CPP macros. gcc at least provides macros that let you do

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 ...
#else
#endif

But these macros aren't ISO C++ standard. The "runtime" check can optimize away to nothing (because the result is a compile-time constant true or false), but the preprocessor lets you disable code that wouldn't even compile.

In C++20, use std::endian type_traits.