在编译时测试endianes:根据标准,这个constexpr函数是否正确

Testing endianess at compile-time: is this constexpr function correct according to the standard?

本文关键字:constexpr 这个 函数 是否 标准 编译 测试 endianes      更新时间:2023-10-16

经过一番搜索,我找到了以下解决方案:

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

GCC只在某些需要constexpr的上下文中接受此代码:

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

对于第二种情况,GCC表示error: accessing value of ‘a’ through a ‘char’ glvalue in a constant expression。我在标准中找不到任何禁止这样做的东西。也许有人可以澄清GCC在哪种情况下是正确的?

这是我从Clang 3.1 ToT:中得到的

错误:constexpr函数从不生成常量表达式

§5.19 [expr.const]

p1某些上下文要求表达满足本款详细规定的附加要求;根据表达式是否满足这些要求,其他上下文具有不同的语义满足这些要求的表达式称为常量表达式

p2条件表达式核心常量表达式

  • […]
  • reinterpret_cast(5.2.10)

因此,(char*)&(a)计算为reinterpret_cast,因此该函数永远不是有效的constexpr函数。

您应该查看Boost.Detail.Endian

它是几个体系结构到其端序的映射(通过宏BOOST_BIG_ENDAN、BOOST_TTLE_ENDIAN和BOOST_PDP_ENDAN)。据我所知,除了这样的列表之外,在编译时没有实际的方法来确定endianness。

对于使用Boost.Detail.Endian的示例实现,您可以看到我希望在提交给Boost时得到审查的库:https://bitbucket.org/davidstone/endian/(相关文件是byte_order.hpp,但如果您只想使用我的实现,unsigned.hpp也是必要的)。

如果实现了N3620-网络字节顺序转换,您将能够使用constexpr ntoh来检查endianness,但请记住,有一些罕见的架构,如middle endian,您永远无法支持所有这些架构。