检查指针是否为空是否安全,然后在同一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
是未定义的行为 )。 没有可移植的方法来测试它们。 (但您可以使用操作系统或处理器特定的技巧)。