2012-02-05 30 views
13

Sau khi một số tìm kiếm một cách để kiểm tra endianess tại thời gian biên dịch tôi đã đi lên với các giải pháp sau đây:Thử nghiệm endianess tại thời gian biên dịch: là hàm constexpr này đúng theo tiêu chuẩn?

static const int a{1}; 

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

GCC chấp nhận mã này chỉ có ở một số bối cảnh nơi constexpr được yêu cầu:

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

Đối với trường hợp thứ hai, GCC cho biết error: accessing value of ‘a’ through a ‘char’ glvalue in a constant expression. Tôi không thể tìm thấy bất cứ điều gì trong tiêu chuẩn cấm điều đó. Có lẽ ai đó có thể làm rõ trong trường hợp nào GCC là chính xác?

+2

Hãy thử biên dịch đầu tiên với cảnh báo trên (gợi ý: đó là VLA). –

+0

Vâng, C++ 11 không có mảng độ dài thay đổi theo như tôi nhớ. Mặc dù vậy, đó là một lỗi khác, vì tôi không nhận được cảnh báo nào với -Wall. BTW, tôi sử dụng GCC-4.7 – p12

+3

Tôi bằng cách nào đó nghi ngờ điều này là có thể, ở cấp độ cơ bản: Endianness là tài sản của việc triển khai *, nhưng phép thuật biên dịch diễn ra hoàn toàn như kết quả của việc áp dụng các quy tắc của * ngôn ngữ *. Đặc biệt, lấy địa chỉ của một đối tượng dường như không phải là một khái niệm biên dịch-thời gian. –

Trả lời

10

Đây là những gì tôi nhận được từ 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);

Vì vậy, (char*)&(a) để đánh giá một reinterpret_cast, như vậy chức năng không bao giờ là một constexpr hàm hợp lệ.

+0

bạn đã tìm kiếm điều đó ở đâu? –

+0

@Matthew: Tôi đã tìm kiếm những gì ở đâu? Câu trích dẫn? Đó là từ tiêu chuẩn C++ 11. – Xeo

+0

Tất nhiên, cảm ơn! –

2

Bạn nên nhìn vào Boost.Detail.Endian

Đó là một ánh xạ của một số kiến ​​trúc để endianness của họ (thông qua BOOST_BIG_ENDIAN macro, BOOST_LITTLE_ENDIAN, và BOOST_PDP_ENDIAN). Theo tôi biết, không có cách nào thực sự để xác định endianness tại thời gian biên dịch, khác với một danh sách như thế này.

Để thực hiện ví dụ sử dụng Boost.Detail.Endian, bạn có thể xem thư viện tôi hy vọng được xem xét để gửi lên: https://bitbucket.org/davidstone/endian/ (tệp có liên quan là byte_order.hpp, nhưng cũng cần thiết nếu bạn muốn) để chỉ sử dụng triển khai của tôi).

0

Nếu N3620 - Chuyển đổi đơn đặt hàng qua mạng được thực hiện, bạn sẽ có thể sử dụng constexpr ntoh để kiểm tra độ tin cậy, nhưng hãy nhớ có những kiến ​​trúc hiếm hoi như trung lưu và bạn sẽ không bao giờ có thể hỗ trợ tất cả chúng.

Các vấn đề liên quan