2016-09-29 56 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