假设 NULL 常量为零是否安全?
NULL 将与 0 比较。
NULL 通常是 非常 零位模式。 NULL 可能是一个非零位模式 - 但这些天没有出现。
OP 混合了至少 4 个东西:NULL、空指针常量、空指针,将 空指针 与 0 进行比较。 C 没有定义 NULL 常量。
NULL
NULL 是一个宏“扩展为实现定义的 null
指针常量”C17dr § 7.19 3
空指针常量
值为 0 的整数常量表达式,或这样的表达式
转换为void * 类型,称为空指针常量。 C17dr § §
6.3.2.3 3
因此,空指针常量的类型可能是int、unsigned、long、...或void *。
当整数常量表达式1时,空指针常量 值为0。像((void *)0)这样的指针,它的值/未指定编码。它普遍存在零位模式,但未指定。
可能有很多空指针常量。它们都相互比较。
注意:空指针常量的大小,当它是整数时,可能与对象指针的大小不同。通常可以通过附加L 或根据需要添加两个后缀来避免这种大小差异。
空指针
如果将空指针常量转换为指针类型,则
结果指针,称为空指针,保证比较
不等于指向任何对象或函数的指针。 C17dr § § 6.3.2.3 3
将空指针转换为另一种指针类型会产生空指针
该类型的指针。任何两个空指针应该比较相等。 C17博士
§ 6.3.2.3 4
空指针的类型是一些指针,要么是像int *, char *这样的对象指针,要么是像int (*)(int, int)或void *这样的函数指针。
空指针的值没有被指定。它普遍存在零位模式,但未指定。
所有空指针比较相等,不管它们的编码。
比较一个空指针和0
if(!ptr) 与 if(!(ptr != 0)) 相同。当指针ptr,它是一个空指针,与0进行比较时,零被转换成一个指针,一个相同类型的空指针:@987654342 @。这 2 个 空指针,可能有不同的位模式,比较相等。
那么什么时候假设 NULL 常量为零是不安全的呢?
NULL 可能是((void*)0),其位模式可能与零不同。无论其编码如何,它确实与上面一样等于 0。已经讨论了调用指针比较,而不是整数比较。将NULL 转换为整数可能不会导致整数值0,即使((void*)0) 是全零位。
printf("%ju\n", (uintmax_t)(uintptr_t)NULL); // Possible not 0
请注意,这是将指针转换为整数,而不是 if(!ptr) 将 0 转换为指针的情况。
C 规范包含许多旧的做事方式,并对新颖的新方式持开放态度。我从未遇到过NULL 不是全零位模式的实现。鉴于存在许多假设 NULL 是全零位的代码,我怀疑只有旧的模糊实现曾经使用过非零位模式 NULL 并且 NULL 几乎可以肯定是全零位模式。
1空指针常量 是 1) 整数或 2) void*。 “当一个整数 ...”指的是第一种情况,而不是 (int)((void*)0) 中第二种情况的强制转换或转换。