C 中的 NULL 与零

NULL vs Zero in C

我最近读了

简而言之,在回答中提到不建议使用 NULL 代替 0 的值,这会导致 UB。

但在中,总之据说假设if(!ptr)//ptr is a pointer并非完全错误。

我知道题目内容不一样,但是怎么解释用NULL代替0是错误的,而if(!ptr)是正确的呢? 因为 if(!ptr) 等同于 if(ptr==0) (我认为这是对的,不确定)。

此外,我已经使用了 if(ptr==0),它对我来说从来没有出错(检查 ptr 是否为 NULL),并且我已将 分配给 0指针 ptr,当我调试代码时 ptr 为 NULL。这两种体验安全吗?

来自this NULL pointer reference

To initialize a pointer to null or to assign the null value to an existing pointer, a null pointer constant (NULL, or any other integer constant with the value zero) may be used.

[强调我的]

所以整数常量0是一个有效的空指针常量。

但要注意,这并不意味着实际使用的硬件平台上的空值等于0,它只是意味着编译器接受0作为系统的别名-依赖空指针常量。

此外,空指针始终是 "false",非空指针始终是 "true",这就是为什么像 if (ptr)if (!ptr) 这样的条件运行良好的原因.

I know the question contents are different, but how could this be explained that using NULL as substitution for 0 is wrong , while if(!ptr) is true? Because if(!ptr) is equivalent to if(ptr==0) (I assume this is right, not sure).

if(!ptr)if 语句的语义上等同于 if (!ptr != 0),在 ! 的语义上等同于 if (ptr == 0)!=== 带有指针操作数的运算符。这是非常一致的,但它并不符合您对整数运算的任何了解。对指针的操作有自己的一套规则。

这就是带回家的东西。因为值为零的整数常量——它是一个源代码构造——除其他外,是一个空指针常量,它根据定义 比较等于所有空指针值。这根本没有说明任何类型的空指针值的表示,关于 NULL 宏扩展到的表达式的类型,或者关于将任何特定的空指针值转换为整数所产生的值不是在源代码中表示为值为零的整数常量。

NULL 是一个宏。这是一个 "implementation-defined null pointer constant;" C17dr § 7.19 3.

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. C17dr § 6.3.2.3 3

所以NULL可能有void *intlongunsignedlong long等类型

0 是一个 int 常量。

没问题的时候

赋值:下面两个都将p,q赋值给某个空指针.

void *p = 0;
void *q = NULL; 

代码比较p==q为真,因为所有空指针都相等。所有空指针不等于任何对象的地址。 !p!q 都是 1。

不正常的时候

函数参数

NULL 的类型及其大小由实现定义。

printf("%d\n", 0);            // OK - %d expects an int
printf("%d\n", NULL);         // Not OK, NULL could be long, void *, etc.
printf("%p\n", NULL);         // Not OK, NULL could be int, long, long long
printf("%p\n", (void*) NULL); // OK - %p expects a void*

_Generic()

下面的结果是实现定义的。

_Generic((NULL), \
  void *: "void *", \
  int: "int", \
  long: "long", \
  default: "TBD")

宏比较

以下结果对我来说是 "error: operator '*' has no right operand"。 #if !0 很好。

#if !NULL
#error foo
#endif