C++ Constexpr指针值
我试图声明初始化为某个常量整数值的constexpr指针,但clang阻止了我的所有尝试: 尝试1:C++ Constexpr指针值,c++,pointers,c++11,clang,constexpr,C++,Pointers,C++11,Clang,Constexpr,我试图声明初始化为某个常量整数值的constexpr指针,但clang阻止了我的所有尝试: 尝试1: constexpr int* x = reinterpret_cast<int*>(0xFF); test.cpp:1:20: note: reinterpret_cast is not allowed in a constant expression 尝试3: constexpr int* x = (int*)0 + 0xFF; test.cpp:1:28: note: ca
constexpr int* x = reinterpret_cast<int*>(0xFF);
test.cpp:1:20: note: reinterpret_cast is not allowed in a constant expression
尝试3:
constexpr int* x = (int*)0 + 0xFF;
test.cpp:1:28: note: cannot perform pointer arithmetic on null pointer
我想做的是设计不允许的吗?若然,原因为何?如果没有,我怎么做
注意:gcc接受所有这些。原因是(这一次,非常有用)错误消息给出的原因:
reinterpret\u cast
不允许在常量表达式中使用。它被列为5.19(第2段)中明确的例外情况之一
将reinterpret\u cast
更改为C样式的cast仍然会在语义上等同于reinterpret\u cast
,因此这没有帮助(而且消息非常明确)
如果你有办法获得一个值为
0
的指针,你确实可以使用p+0xff
,但是我想不出一个方法来获得一个带有常量表达式的指针。您可以依赖于实现上的值为0
的空指针值(0
在指针上下文中,就像您所做的那样,或者nullptr
),但正如您自己看到的,您的实现拒绝这样做。我想这是允许的。(例如,大多数常量表达式允许实现退出。)正如Luc Danton所指出的,[expr.const]/2中的规则阻止了您的尝试,该规则规定核心常量表达式中不允许使用各种表达式,包括:
--重新解释演员阵容
--具有未定义行为的操作[注意:包括[…]某些指针算术[…]--结束注意]
第一个项目排除了你的第一个例子。第二个示例被上面的第一个项目符号以及[expr.cast]/4中的规则排除,即:
[…]areinterpret_cast
[…]执行的转换可以使用显式类型转换的强制转换表示法执行。同样的语义限制和行为也适用
第二个项目符号是由添加的,它澄清了常量表达式中不允许对空指针执行指针算术。这排除了你的第三个例子
即使这些限制不适用于核心常量表达式,也不可能使用通过强制转换整数生成的值初始化constepr
指针,因为constepr指针变量必须由地址常量表达式初始化,而地址常量表达式必须通过[expr.const]/3计算为
具有静态存储持续时间的对象地址、函数地址或空指针值
转换为指针类型的整数不属于这些类型
g++还没有严格执行这些规则,但其最新版本已经越来越接近这些规则,因此我们应该假设它最终将完全实现这些规则
如果您的目标是声明执行静态初始化的变量,那么只需删除constexpr
——clang和g++都将为此表达式发出静态初始值设定项。如果出于某种原因需要将此表达式作为常量表达式的一部分,则有两种选择:
- 重新构造代码,以便传递intptr_t而不是指针,并在需要时将其转换为指针类型(在常量表达式之外),或
- 是否使用
。这种精确的表达式形式(在条件运算符的左侧有\u内置常数\u p((int*)0xFF)?(int*)0xFF:(int*)0xFF
)在条件运算符的臂中禁用严格的常量表达式检查,是一种鲜为人知的、但不可移植的GNU扩展,由gcc和clang支持\uuu内置常量\u p
0xff/sizeof(*x)
。
constexpr int* x = (int*)0 + 0xFF;
test.cpp:1:28: note: cannot perform pointer arithmetic on null pointer