constexpr中的字节序

时间:2016-06-16 18:04:47

标签: c++ language-lawyer endianness constant-expression

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

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

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

2 个答案:

答案 0 :(得分:9)

无。事实上,该计划是不正确的。来自[expr.const]:

  

条件表达式e是核心常量表达式,除非e的评估遵循规则   抽象机器(1.9),将评估以下表达式之一:
    - [...]
    - 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
}

答案 1 :(得分:2)

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

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

通过union输入惩罚失败,因为您根本不允许在C ++中通过union输入双关语。即使你再次......,C ++也不会将实现限制为大或小端序。

因此,就C ++而言,无论是在编译时还是在运行时,都无法检测到它。