在 C++ 中进行常量评估期间,悬挂指针是否可以等于有效指针?
Can dangling pointer be equal to valid pointer during constant evaluation in C++?
在 C++17 中的常量表达式求值期间,编译器是否应将寻址有效对象的任何指针视为不等于寻址对象生命周期结束后的任何指针?
例如:
constexpr auto f(int * x = nullptr) {
int c = 0;
auto p = &c;
if ( x == p )
throw "unexpected";
return p;
};
int main() {
static_assert( f( f() ) );
}
这里函数f()
的内部调用returns一个悬空指针,再次传递给f
。我认为条件 x == p
必须是 false
因为 x
是一个悬空指针而 p
是一个有效指针,在 Clang 中确实如此。但在 GCC 中,条件得到满足,并且由于 throw
,常量评估失败。演示:https://gcc.godbolt.org/z/ehcMro17q
它是未定义或实现定义的行为,还是其中一个编译器错误?
悬挂指针与任何其他指针的比较结果是实现定义的:
When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. […] Any other use of an invalid pointer value has implementation-defined behavior.
([basic.stc]/4)(这里的“其他用途”中包含相等比较。)
如评论中所述,即使是比较操作数的左值到右值转换也会为无效指针调用实现定义的行为 ([conv.lval]/3.3)。不幸的是,我找不到任何强制 相等比较操作数的左值到右值转换; [expr.eq]/2 充其量只能非常间接地暗示这一点。
在 C++17 中的常量表达式求值期间,编译器是否应将寻址有效对象的任何指针视为不等于寻址对象生命周期结束后的任何指针?
例如:
constexpr auto f(int * x = nullptr) {
int c = 0;
auto p = &c;
if ( x == p )
throw "unexpected";
return p;
};
int main() {
static_assert( f( f() ) );
}
这里函数f()
的内部调用returns一个悬空指针,再次传递给f
。我认为条件 x == p
必须是 false
因为 x
是一个悬空指针而 p
是一个有效指针,在 Clang 中确实如此。但在 GCC 中,条件得到满足,并且由于 throw
,常量评估失败。演示:https://gcc.godbolt.org/z/ehcMro17q
它是未定义或实现定义的行为,还是其中一个编译器错误?
悬挂指针与任何其他指针的比较结果是实现定义的:
When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. […] Any other use of an invalid pointer value has implementation-defined behavior.
([basic.stc]/4)(这里的“其他用途”中包含相等比较。)
如评论中所述,即使是比较操作数的左值到右值转换也会为无效指针调用实现定义的行为 ([conv.lval]/3.3)。不幸的是,我找不到任何强制 相等比较操作数的左值到右值转换; [expr.eq]/2 充其量只能非常间接地暗示这一点。