我想创建一个返回系统字节序的 constexpr 函数,如下所示:
constexpr bool IsBigEndian()
{
constexpr int32_t one = 1;
return (reinterpret_cast<const int8_t&>(one) == 0);
}
现在,由于函数将在编译时而不是在实际的目标机器上执行,C++ 规范提供什么保证来确保返回正确的结果?
我想创建一个返回系统字节序的 constexpr 函数,如下所示:
constexpr bool IsBigEndian()
{
constexpr int32_t one = 1;
return (reinterpret_cast<const int8_t&>(one) == 0);
}
现在,由于函数将在编译时而不是在实际的目标机器上执行,C++ 规范提供什么保证来确保返回正确的结果?
没有任何。事实上,这个程序是错误的。来自 [expr.const]:
条件表达式 e 是一个核心常量表达式,除非按照抽象机 (1.9) 的规则对 e 的求值将求值以下表达式之一:
— [...]
— areinterpret_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
}
正如 Barry 所说,您的代码不是合法的 C++。然而,即使你拿走了这constexpr
部分,它仍然不是合法的 C++。您的代码违反了严格的别名规则,因此代表未定义的行为。
事实上,在 C++ 中没有办法在不调用未定义行为的情况下检测对象的字节顺序。将其转换为 achar*
不起作用,因为该标准不需要大端或小端顺序。因此,虽然您可以通过一个字节读取数据,但您将无法从该值合法地推断出任何内容。
并且通过 aunion
键入双关语失败,因为您根本不允许union
在 C++ 中通过 a 键入双关语。即使你这样做了......再次,C++ 不会将实现限制为大端或小端顺序。
因此,就 C++ 作为标准而言,无论是在编译时还是运行时,都无法检测到这一点。