2016-09-29 1 views
12

이 주제에 대해 많은 질문을 받았지만 지금까지는 해결책을 찾지 못했습니다. 여기에 하나의 자연 해법이 언급되었습니다 : 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를 결정하는 데 결정적인 방법으로 간주 될 수 있습니까? 아니면 type-punning 또는 다른 것을 놓치지 않을 수 있습니까?

+2

'uint8_t (u2.i)'가 endianness에서 동일한 값을 생성하지 않습니까? 캐스트는 첫 번째 바이트를 선택하는 것이 아니라 값을 보존해야합니다. –

+1

4 바이트 정수 내에 24 개의 가능한 바이트 순서가 있습니다. 적어도 실제 컴퓨터에서는 3 개가 사용되었습니다. 또한 [[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'와 동일)을 체크하면 잘 동작합니다. 이 솔루션은 많은 다른 답변에 있습니다. 그러나 그것들은 런타임에만 제한됩니다. 'constexpr' 제한으로 인해 컴파일 타임이 작동하지 않습니다. 여기서 U1과 U2는 서로 거울처럼 작용합니다. 컴파일 시간을 허용하기 위해 컴파일러를 트릭하려고했습니다. 그것이 틀릴 수도 있습니다. 그러나 빅 엔디 언 (Big Endian)에서 누군가 확인하면 좋다. – iammilind

관련 문제