检查指针是否为空是否安全,然后在同一if语句中取消引用它?

如果传入空指针,以下代码是否安全?

if(ptr && *ptr == value) { //do something } 

检查的顺序是否重要? 如果我改成它,它会起作用吗?

 if(*ptr == value && ptr) { //do something } 

前者是正确和安全的,后者则不是。

内置的&&运算符具有短路语义 ,这意味着当且仅当第一个参数为真时才计算第二个参数。

(对于重载运算符,情况并非如此。)

是(1)因短路而安全。 这是评估逻辑语句的方式。 如果&&语句的第一部分为false,则整个语句永远不会为true,因此它不会尝试评估第二部分。

(2)是不安全的,因为它首先取消引用空指针,这是未定义的行为。

编辑:

参考下面的KerrekSBs注释: 为什么解除引用空指针是未定义的行为?

从该post的第一个答案:

定义解除引用NULL指针的一致行为将要求编译器在大多数CPU体系结构上的每次取消引用之前检查NULL指针。 对于专为速度而设计的语言而言,这是一种令人无法接受的现象。

还有(历史上)硬件,其中由NULL (不总是0 )指向的存储器实际上在程序中是可寻址的并且可以被解除引用。 因此,由于缺乏共识和一致性,因此决定取消引用空指针将是“未定义的行为”

如果指针无效(或者指出为NULL ),则在第一个版本中,短路将阻止评估*ptr == value ,因此第一个是安全的。

第二个将始终访问*ptr ,无论它是否有效。

除了关于ptr && *ptr == value有效的所有其他答案,但不是相反,有效指针的概念可能具有不同的含义。

ptr可以是未初始化的变量,或者可以以这样的方式获得(例如,通过来自某个随机intptr_t整数的转换),使得它不指向任何地方(例如悬空指针 )但不是空的。

在这种情况下,测试的顺序都不起作用。

一些指针可能无效并且为非null(然后测试ptr && *ptr == value未定义的行为 )。 没有可移植的方法来测试它们。 (但您可以使用操作系统或处理器特定的技巧)。