错误: 从整数到指针的reinterpret_cast

17 浏览
0 Comments

错误: 从整数到指针的reinterpret_cast

我试图声明一个constexpr指针,将其初始化为某个常量整数值,但是clang却挫败了我所有的尝试:\n尝试1:\n

constexpr int* x = reinterpret_cast(0xFF);
test.cpp:1:20: 注意:reinterpret_cast在常量表达式中不允许使用

\n尝试2:\n

constexpr int* x = (int*)0xFF;
test.cpp:1:20: 注意:执行reinterpret_cast的强制转换在常量表达式中不允许使用

\n尝试3:\n

constexpr int* x = (int*)0 + 0xFF;
test.cpp:1:28: 注意:不能在空指针上进行指针算术运算

\n我尝试的这个操作是不允许的吗?如果是,为什么?如果不是,我该如何做到呢?\n注意:gcc接受了所有这些操作。

0
0 Comments

这个问题出现的原因是因为在常量表达式中,不允许使用reinterpret_cast。这在5.19(第2段)中被明确列为一个例外情况。

将reinterpret_cast改为C风格的转换仍然相当于reinterpret_cast的语义等效,所以这并没有帮助(错误消息也非常明确)。

如果你有一种方法可以获得一个值为0的指针,那么你确实可以使用p + 0xff。但是我想不出一种在常量表达式中获得这样一个指针的方法。你可以依赖于空指针值(在指针上下文中使用0,或者nullptr)在你的实现中具有0的值,但正如你自己所看到的,你的实现拒绝这样做。我认为这是允许的(例如,大多数常量表达式都可以中途退出)。

他应该添加的是0xff/sizeof(*x)。

0
0 Comments

错误信息 "reinterpret_cast from integer to pointer" 表示试图将整数强制转换为指针类型时发生了错误。这个问题的出现是由于在核心常量表达式中,根据[expr.const]/2的规则,禁止使用各种表达式,包括:

- reinterpret_cast操作符

- 会导致未定义行为的操作(包括某些指针算术)

第一个规则排除了第一个示例的情况。第二个示例被上述第一个规则以及[expr.cast]/4中的规则所排除,该规则规定:

- 由reinterpret_cast执行的转换可以使用显式类型转换的转换表示法进行。相同的语义限制和行为适用。

第二个规则是由WG21核心问题1313添加的,并且明确指出在常量表达式中不允许对空指针进行指针算术运算。这排除了第三个示例的情况。

即使这些限制不适用于核心常量表达式,使用整数转换初始化constexpr指针也是不可能的,因为根据[expr.const]/3,constexpr指针变量必须由地址常量表达式进行初始化,该表达式必须计算为:

- 具有静态存储期的对象的地址

- 函数的地址

- 空指针值

整数转换为指针类型不属于这些情况之一。

虽然g++目前还没有严格执行这些规则,但是最近的版本已经越来越接近,因此我们应该假设它最终会完全实现这些规则。

如果您的目标是声明一个进行静态初始化的变量,您可以简单地删除constexpr - clang和g++都将为此表达式生成静态初始化程序。如果由于某种原因需要将此表达式作为常量表达式的一部分,有两种选择:

- 重构代码,以便在需要时传递intptr_t而不是指针,并在常量表达式之外将其转换为指针类型。

- 使用__builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF。此形式的表达式(在条件运算符的左侧使用__builtin_constant_p)会在条件运算符的各个分支中禁用严格的常量表达式检查,这是一个鲜为人知但受到gcc和clang支持的非可移植GNU扩展,已经有文档说明。

0