HC4*_*ica 29 c++ pointers clang constexpr c++11
我试图声明一个constexpr指针初始化为一些常量整数值,但clang正在挫败我所有的尝试:
尝试1:
constexpr int* x = reinterpret_cast<int*>(0xFF);
test.cpp:1:20: note: reinterpret_cast is not allowed in a constant expression
Run Code Online (Sandbox Code Playgroud)
尝试2:
constexpr int* x = (int*)0xFF;
test.cpp:1:20: note: cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression
Run Code Online (Sandbox Code Playgroud)
尝试3:
constexpr int* x = (int*)0 + 0xFF;
test.cpp:1:28: note: cannot perform pointer arithmetic on null pointer
Run Code Online (Sandbox Code Playgroud)
是我试图不允许的设计?如果是这样,为什么?如果没有,我该怎么办?
注意:gcc接受所有这些.
Ric*_*ith 22
正如Luc Danton所说,你的尝试被[expr.const]/2中的规则所阻止,这些规则表明核心常量表达式中不允许使用各种表达式,包括:
- a
reinterpret_cast
- 具有未定义行为的操作[注意:包括[...]某些指针算法[...] - 结束注释]
第一个子弹排除了你的第一个例子.第二个例子由上面的第一个子弹排除,加上[expr.cast]/4的规则:
[...]
reinterpret_cast[...] 执行的转换可以使用显式类型转换的强制转换表示法执行.适用相同的语义限制和行为.
WG21核心问题1313添加了第二个项目符号,并阐明了在常量表达式中不允许对空指针进行指针运算.这排除了你的第三个例子.
即使这些限制不适用于核心常量表达式,仍然无法初始化具有constexpr通过转换整数产生的值的指针,因为constexpr指针变量必须由地址常量表达式初始化,通过[expr] .const]/3,必须评估
具有静态存储持续时间的对象的地址,函数的地址或空指针值.
转换为指针类型的整数不是这些.
g ++还没有严格执行这些规则,但它最近的版本已经越来越接近它们,所以我们应该假设它最终将完全实现它们.
如果你的目标是声明一个执行静态初始化的变量,你可以简单地删除constexpr- clang和g ++都会为这个表达式发出一个静态初始化器.如果由于某种原因需要将此表达式作为常量表达式的一部分,则有两种选择:
__builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF.这种精确的表达形式(__builtin_constant_p在条件运算符的左侧)禁用条件运算符的严格常量表达式检查,并且是一个鲜为人知但有记录的,不可移植的GNU扩展,由两者支持gcc和clang.原因是(一次,非常有用)错误消息给出的一个:reinterpret_cast在常量表达式中不允许.它被列为5.19(第2段)中的明确例外之一.
将更reinterpret_cast改为C风格的强制转换仍然以语义等效于a结束reinterpret_cast,因此无效(并且消息非常明确).
如果你有办法获得一个有价值的指针0你可以使用,p + 0xff但我想不出一种方法来获得这样一个带有常量表达式的指针.您可以依赖空指针值(0在指针上下文中,就像您所做的那样),或者在您的实现上nullptr具有值,0但正如您自己所见,您的实现拒绝这样做.我认为这样做是可以的.(例如,对于大多数常量表达式,允许实现豁免.)