简体   繁体   中英

Determining endianness of integers in array

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?

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM