2016-09-29 67 views
12

我已经在这个主题上提到了SO中的许多问题,但到目前为止找不到任何解决方案。这里提到了一个自然的解决方案:Determining endianness at compile time
但是,在评论&中提到的相关问题的答案相同。在编译时使用C++编程式地查找字节序列号11

经过一些修改,我可以用g ++ & clang ++(-std=c++11)编译一个类似的解决方案,没有任何警告。

static_assert(sizeof(char) == 1, "sizeof(char) != 1"); 
union U1 
{ 
    int i; 
    char c[sizeof(int)]; 
}; 
union U2 
{ 
    char c[sizeof(int)]; 
    int i; 
}; 

constexpr U1 u1 = {1}; 
constexpr U2 u2 = {{1}}; 
constexpr bool IsLittleEndian() 
{ 
    return u1.i == u2.c[0]; // ignore different type comparison 
} 

static_assert(IsLittleEndian(), "The machine is BIG endian"); 

Demo

这可以被认为是一个确定性的方法来决定endian - ness或错过类型双关或其他?

+2

uint8_t(u2.i)'不会在任何字节序上产生相同的值吗?强制转换应该是值得保留的,而不仅仅是选择第一个字节。 –

+1

在4字节整数内有24个可能的字节顺序。至少*三台电脑已被实际电脑使用。此外,对[['un']'signed']'char'的严格别名规则的例外情况也适用于'uint8_t'并不完全清楚。 –

+0

@BoPersson,我想避免任何有关“不同大小类型比较”的编译器警告(正如我在Q中声称的那样)。从这里开始,1会用最小的类型表示,我发现它可以用于类型转换。或者我误解了你的担忧?我会修改一下代码。 – iammilind

回答

1

您试图从没有什么不同,这显然不工作的一个(其中IsLittleEndian()等同于true):

constexpr char c[sizeof(int)] = {1}; 
constexpr int i = {1}; 
constexpr bool IsLittleEndian() 
{ 
    return i == c[0]; // ignore different type comparison 
} 

static_assert(IsLittleEndian(), "The machine is BIG endian"); 

我相信C++ 11并没有提供手段来编程确定的字节序编译期间的目标平台。我的论点是唯一有效的方式来运行是期间执行该检查使用unsigned char指针(因为类型双关的其它方式不可避免地含有不确定的行为)来检查一个变量int

const uint32_t i = 0xffff0000; 

bool isLittleEndian() { 
    return 0 == *reinterpret_cast<const unsigned char*>(&i); 
} 

C++ 11不允许执行此功能constexpr,因此在编译期间无法执行此检查。

+0

您能否更详细地解释为什么试图解决方案不起作用?或者为什么它与你在回答开始时提到的那个(非工作)相同。我没有机会检查一台大型机器,但是我认为你所说的是真实的。但问题是为什么? – iammilind

+0

@iammilind工会在你的“解决方案”中服务的目的是什么?你永远不会访问/使用'U1 :: c',你永远不会访问/使用'U2 :: i'。因此,消除它们后,我们到达我的版本。 – Leon

+0

2个工会只是为了消除编译器错误,否则与1联合。如果你检查'u1.i == u1.c [0]'(与'u2'相同),那么它工作正常。这个解决方案在SO中有很多其他的答案。但那些仅限于运行时。由于'constexpr'的限制,它们不能编译时间。这里U1和U2互为镜像。我试图欺骗编译器以允许编译时。可能是错的。但是,如果有人用大端排序来检查它会很好。 – iammilind