2012-02-05 10 views
13

Po jakimś poszukiwaniu sposobu, aby sprawdzić kolejność bajtów w czasie kompilacji Mam wymyślić następujące rozwiązanie:Testowanie endianess podczas kompilacji: czy ta funkcja constexpr jest poprawna zgodnie ze standardem?

static const int a{1}; 

constexpr bool is_big_endian() 
{ 
    return *((char*)&(a)) == 1; 
} 

GCC akceptuje ten kod tylko w niektórych sytuacjach, w których wymagana jest constexpr:

int b[is_big_endian() ? 12 : 25]; //works 
std::array<int, testendian() ? 12 : 25> c; //fails 

W drugim przypadku GCC mówi: error: accessing value of ‘a’ through a ‘char’ glvalue in a constant expression. Nie mogłem znaleźć niczego w standardzie, który zabrania czegoś takiego. Może ktoś mógłby wyjaśnić, w którym przypadku GCC jest poprawne?

+2

Spróbuj skompilować pierwszą z ostrzeżeniami na (wskazówka: jest to VLA). –

+0

Cóż, C++ 11 nie ma tablic o zmiennej długości, o ile pamiętam. Chociaż, to jest inny błąd, ponieważ nie otrzymuję ostrzeżeń za pomocą -Wall. BTW, używam GCC-4.7 – p12

+3

Wątpię, czy jest to możliwe na podstawowym poziomie: Endianness jest właściwością * realizacji *, ale magia kompilacji dzieje się wyłącznie w wyniku stosowania reguł * języka *. W szczególności przyjęcie adresu obiektu nie wydaje się być pojęciem kompilacji. –

Odpowiedz

10

To, co dostaję od Clang 3.1 ToT:

error: constexpr function never produces a constant expression

§5.19 [expr.const]

p1 Certain contexts require expressions that satisfy additional requirements as detailed in this sub-clause; other contexts have different semantics depending on whether or not an expression satisfies these requirements. Expressions that satisfy these requirements are called constant expressions.

p2 A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression:

  • [...]
  • a reinterpret_cast (5.2.10);

Więc (char*)&(a) ocenia na reinterpret_cast jako taka funkcja nie jest ważna funkcja constexpr.

+0

gdzie to wyglądasz? –

+0

@Matthew: Gdzie się dowiedziałem co? Cytat? To ze standardu C++ 11. – Xeo

+0

Oczywiście, dzięki! –

2

Należy zajrzeć do Boost.Detail.Endian

Jest to odwzorowanie kilku architektur ich endianness (poprzez BOOST_BIG_ENDIAN makr BOOST_LITTLE_ENDIAN i BOOST_PDP_ENDIAN). O ile mi wiadomo, nie ma rzeczywistego sposobu określenia endianiczności w czasie kompilacji, poza listą taką jak ta.

Dla przykładowej implementacji, który używa Boost.Detail.Endian można zobaczyć bibliotekę mam nadzieję dostać przeglądowi składania Boost: https://bitbucket.org/davidstone/endian/ (odpowiedni plik jest byte_order.hpp, ale unsigned.hpp jest niezbędne, jak również, jeśli chcesz po prostu użyć mojej implementacji).

0

Jeśli N3620 - Konwersja zleceń bajtów sieciowych jest zaimplementowana, będziesz mógł użyć constexpr ntoh, aby sprawdzić endianness, ale pamiętaj, że istnieją rzadkie architektury, takie jak middle-endian i nigdy nie będziesz w stanie obsłużyć wszystkich im.

Powiązane problemy