14

我想创建一个返回系统字节序的 constexpr 函数,如下所示:

constexpr bool IsBigEndian()
{
    constexpr int32_t one = 1;
    return (reinterpret_cast<const int8_t&>(one) == 0);
}

现在,由于函数将在编译时而不是在实际的目标机器上执行,C++ 规范提供什么保证来确保返回正确的结果?

4

2 回答 2

10

没有任何。事实上,这个程序是错误的。来自 [expr.const]:

条件表达式 e 是一个核心常量表达式,除非按照抽象机 (1.9) 的规则对 e 的求值将求值以下表达式之一:
— [...]
— a reinterpret_cast
— [...]

并且,来自 [dcl.constexpr]:

对于既不是默认值也不是模板的constexpr函数或constexpr构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式 (5.20) 的求值子表达式,或者对于构造函数,是常量初始值设定项对于某些对象(3.6.2),程序格式错误;无需诊断。


这样做的方法只是希望您的编译器足够好,可以为您的机器的字节序提供宏。例如,在 gcc 上,我可以使用__BYTE_ORDER__

constexpr bool IsBigEndian() {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    return false;
#else
    return true;
#endif
}
于 2016-06-16T18:12:59.863 回答
2

正如 Barry 所说,您的代码不是合法的 C++。然而,即使你拿走了这constexpr部分,它仍然不是合法的 C++。您的代码违反了严格的别名规则,因此代表未定义的行为。

事实上,在 C++ 中没有办法在不调用未定义行为的情况下检测对象的字节顺序。将其转换为 achar*不起作用,因为该标准不需要大端或小端顺序。因此,虽然您可以通过一个字节读取数据,但您将无法从该值合法地推断出任何内容。

并且通过 aunion键入双关语失败,因为您根本不允许union在 C++ 中通过 a 键入双关语。即使你这样做了......再次,C++ 不会将实现限制为大端或小端顺序。

因此,就 C++ 作为标准而言,无论是在编译时还是运行时,都无法检测到这一点。

于 2016-06-16T18:31:17.477 回答