Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Constexpr指针值_C++_Pointers_C++11_Clang_Constexpr - Fatal编程技术网

C++ Constexpr指针值

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指针,但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: 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中的规则排除,即:

[…]a
reinterpret_cast
[…]执行的转换可以使用显式类型转换的强制转换表示法执行。同样的语义限制和行为也适用

第二个项目符号是由添加的,它澄清了常量表达式中不允许对空指针执行指针算术。这排除了你的第三个例子

即使这些限制不适用于核心常量表达式,也不可能使用通过强制转换整数生成的值初始化
constepr
指针,因为constepr指针变量必须由地址常量表达式初始化,而地址常量表达式必须通过[expr.const]/3计算为

具有静态存储持续时间的对象地址、函数地址或空指针值

转换为指针类型的整数不属于这些类型

g++还没有严格执行这些规则,但其最新版本已经越来越接近这些规则,因此我们应该假设它最终将完全实现这些规则

如果您的目标是声明执行静态初始化的变量,那么只需删除
constexpr
——clang和g++都将为此表达式发出静态初始值设定项。如果出于某种原因需要将此表达式作为常量表达式的一部分,则有两种选择:

  • 重新构造代码,以便传递intptr_t而不是指针,并在需要时将其转换为指针类型(在常量表达式之外),或
  • 是否使用
    \u内置常数\u p((int*)0xFF)?(int*)0xFF:(int*)0xFF
    。这种精确的表达式形式(在条件运算符的左侧有
    \uuu内置常量\u p
    )在条件运算符的臂中禁用严格的常量表达式检查,是一种鲜为人知的、但不可移植的GNU扩展,由gcc和clang支持

为什么这里需要constexpr?如果你不使用函数,constexpr实际上不是和const一样吗?@RobertMason:例如,如果它是一个类的静态成员,而不是constexpr,我不能在线初始化它。也许静态内联成员函数比数据成员更合适。@HighCommander4:你不允许初始化ints内联吗?指针是下面的整数(不是全部),所以即使它不是完全标准的(我不知道,我身上没有标准的副本),你也应该能够让大多数编译器接受它。@RobertMason:clang和gcc不接受非constexpr指针的行内初始化。我不知道为什么——我也想知道原因。他补充说应该是
0xff/sizeof(*x)
constexpr int* x = (int*)0 + 0xFF;

test.cpp:1:28: note: cannot perform pointer arithmetic on null pointer