检查指针是不是为空,然后在同一个 if 语句中取消引用它是不是安全?
Posted
技术标签:
【中文标题】检查指针是不是为空,然后在同一个 if 语句中取消引用它是不是安全?【英文标题】:Is it safe to check if a pointer is null, then dereference it in the same if statement?检查指针是否为空,然后在同一个 if 语句中取消引用它是否安全? 【发布时间】:2012-11-26 18:50:16 【问题描述】:如果传入空指针,下面的代码是否安全?
if(ptr && *ptr == value)
//do something
检查的顺序重要吗?改成这个有效果吗?
if(*ptr == value && ptr)
//do something
【问题讨论】:
我已经编辑了问题标题,以澄清“有效指针”的意思是“非空”。 【参考方案1】:如果指针无效(或者更确切地说是NULL
,正如指出的那样),在第一个版本中short-circuiting 将阻止对*ptr == value
的评估,所以第一个是安全的。
第二个总是访问*ptr
,不管它是否有效。
【讨论】:
if (ptr)
无法检查 invalid 指针。它只能检查 null 指针。
@KerrekSB 我假设“无效”在这里指的是“NULL
”。除此之外,您必须知道,在 C++ 中检测指向无处的指针是相当困难的。
根据您阅读标准的方式,空指针实际上可能是一个完美的有效指针。我更喜欢将“无效指针”一词保留为不再存在的对象的地址或非法指针运算的结果。该标准有一个关于“安全派生指针”(3.7.4.3)的部分。【参考方案2】:
是的 (1) 是安全的,因为短路。这是评估逻辑语句的方式。如果&&
语句的第一部分为假,则整个语句永远不会为真,因此它不会尝试评估第二部分。
和 (2) 是不安全的,因为它首先取消引用空指针,这是未定义的行为。
编辑:
参考下面的 KerrekSBs 评论: Why dereferencing a null pointer is undefined behaviour?
来自该帖子的第一个答案:
为取消引用 NULL 指针定义一致的行为将 要求编译器在每个之前检查 NULL 指针 大多数 CPU 架构的取消引用。这是一个不能接受的 为速度而设计的语言的负担。
还有(历史上是)硬件,其中NULL
(并非总是0
)指向的内存实际上在程序中是可寻址的并且可以取消引用。因此,由于缺乏共识和一致性,决定取消引用空指针将是“未定义的行为”
【讨论】:
(2) 不只是“不安全”;这是彻头彻尾的未定义行为。 @KerrekSB:你最好详细说明一下你提出的区别。 @Mehrdad:嗯,gets
不安全,因为您不知道所需的缓冲区长度,而printf
不安全,因为您可以传递错误类型的参数。 “不安全”是指无法静态验证代码的正确性。这与取消引用空指针完全不同,后者总是很糟糕。
物理上,空指针不一定绑定到地址0
。它可以由任何特定于平台的地址表示。
@KerrekSB:从技术上讲,这并不“总是”不好,对吧?实现很可能会确定它是该特定系统的有效操作,在这种情况下它将是完全安全的......它不像标准 要求 它是未定义的行为。所以我并没有真正看到“不安全”和“未定义”之间的显着区别(尽管正如你提到的那样它肯定是无法验证的)。【参考方案3】:
前者正确安全,后者不正确。
内置的&&
运算符具有短路语义,这意味着当且仅当第一个参数为真时才计算第二个参数。
(对于 重载 运算符,情况并非如此。)
【讨论】:
感谢未定义的行为指针 - 我从事实践已经很长时间了,并且经常对细节缺乏兴趣 - 我现在正在尝试补救。【参考方案4】:除了所有其他关于ptr && *ptr == value
有效但不是相反的答案之外,有效指针的概念可能具有不同的含义。
ptr
可能是一个未初始化的变量,或者可以通过不指向任何地方(例如 dangling pointer)但不是空。
在这种情况下,测试顺序都不起作用。
一些指针可能是无效的并且是非空的(那么测试ptr && *ptr == value
是未定义的行为)。没有可移植的方法来测试它们。 (但您可以使用操作系统或处理器特定的技巧)。
【讨论】:
以上是关于检查指针是不是为空,然后在同一个 if 语句中取消引用它是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章
如何在javascript中执行if语句来检查JSON数组是不是为空?