通过 "myPtr > 0" 检查空指针
Null pointer check via "myPtr > 0"
在一些遗留代码中,我遇到了以下空指针检查。
if( myPtr > 0 ) {
...
}
通过此 if-check 检查空指针是否存在任何技术风险?
指针和整数之间的有序比较在 C++ 中是 ill-formed(即使整数是空指针常量,例如在本例中)。风险在于编译器被允许并且确实拒绝编译此类代码。
您可以将其重写为以下任一形式:
if(myPtr != nullptr)
if(myPtr)
0
是一个 NULL 常量。所以这相当于 ptr > (void*)0
.
问题是 C++ 中指针的 >
仅对指向同一对象或数组的指针有效。这条规则起源于过去,当时像分段内存这样相对疯狂的东西更常见,但它允许编译器进行优化和假设。
例如,假设 px
是指向数组的指针,并且它当前指向第一个元素。那么 px>py
为真,除非 py
也是指向第一个元素的指针。或者,如果 px
是指向数组 one-past-the-end 的指针,则 px<py
始终为 false。
使用这种知识,编译器可以理解重构和重写循环边界,这反过来可以让编译器生成更快的代码。
但这也意味着 px>py
可能在一个地方为真而在另一个地方不为真,因为编译器可以在一个地方证明关于 py
的事实,但不能在另一个地方证明。
简而言之,指针比较要非常小心。
同时,null 和任何其他指针之间的相等性已明确定义。
也保证std::less
行为良好,在定义<
时同意<
;这允许指针映射工作。
在这种情况下,正确的重写是:
if(myPtr!=nullptr)
如果 myPtr
不是指针,或者
将无法编译
if(myPtr)
如果 myPtr
是带符号的数字类型,则存在您刚刚更改行为的风险。我会做第一个。
正如其他人所说,比较无效,因此行为取决于编译器。许多操作系统可能认为指针是有符号的,因为它们将地址 space 分成两半,负数属于内核,因此那里的编译器可能会为 myPtr > 0
发出带符号的比较
有几个案例我看到编译器认为指针是带符号的,但我现在找不到它们。但一个值得注意的例子是 POINTER_SIGNED
and POINTER_UNSIGNED
macros in Windows which resolves to __sptr
and __uptr
另见
- comparing pointer to a negative value
- Must allocated memory address be positive in user space of all platforms
- Pointer comparisons in C. Are they signed or unsigned?
在一些遗留代码中,我遇到了以下空指针检查。
if( myPtr > 0 ) {
...
}
通过此 if-check 检查空指针是否存在任何技术风险?
指针和整数之间的有序比较在 C++ 中是 ill-formed(即使整数是空指针常量,例如在本例中)。风险在于编译器被允许并且确实拒绝编译此类代码。
您可以将其重写为以下任一形式:
if(myPtr != nullptr)
if(myPtr)
0
是一个 NULL 常量。所以这相当于 ptr > (void*)0
.
问题是 C++ 中指针的 >
仅对指向同一对象或数组的指针有效。这条规则起源于过去,当时像分段内存这样相对疯狂的东西更常见,但它允许编译器进行优化和假设。
例如,假设 px
是指向数组的指针,并且它当前指向第一个元素。那么 px>py
为真,除非 py
也是指向第一个元素的指针。或者,如果 px
是指向数组 one-past-the-end 的指针,则 px<py
始终为 false。
使用这种知识,编译器可以理解重构和重写循环边界,这反过来可以让编译器生成更快的代码。
但这也意味着 px>py
可能在一个地方为真而在另一个地方不为真,因为编译器可以在一个地方证明关于 py
的事实,但不能在另一个地方证明。
简而言之,指针比较要非常小心。
同时,null 和任何其他指针之间的相等性已明确定义。
也保证std::less
行为良好,在定义<
时同意<
;这允许指针映射工作。
在这种情况下,正确的重写是:
if(myPtr!=nullptr)
如果 myPtr
不是指针,或者
if(myPtr)
如果 myPtr
是带符号的数字类型,则存在您刚刚更改行为的风险。我会做第一个。
正如其他人所说,比较无效,因此行为取决于编译器。许多操作系统可能认为指针是有符号的,因为它们将地址 space 分成两半,负数属于内核,因此那里的编译器可能会为 myPtr > 0
有几个案例我看到编译器认为指针是带符号的,但我现在找不到它们。但一个值得注意的例子是 POINTER_SIGNED
and POINTER_UNSIGNED
macros in Windows which resolves to __sptr
and __uptr
另见
- comparing pointer to a negative value
- Must allocated memory address be positive in user space of all platforms
- Pointer comparisons in C. Are they signed or unsigned?