我最近读过一篇文章,我可以用NULL代替0的值吗?
简而言之,在回答中提到,不建议使用NULL来代替0
的值,这将导致UB。
但是在假设NULL常量为零是否安全?中?,简而言之,假设CCD_ 2不是完全错误的。
我知道问题的内容是不同的,但这怎么解释用NULL代替0是错误的,而if(!ptr)
是真的呢?因为if(!ptr)
等价于if(ptr==0)
(我认为这是对的,不确定(。
此外,我使用了if(ptr==0)
,它对我来说从未出错(检查ptr
是否为NULL(,并且我将0
分配给指针ptr
,当我调试代码时,ptr
为NULL。这两种体验安全吗?
从此NULL
指针引用:
要将指针初始化为null或将null值分配给现有指针,可以使用null指针常量(
NULL
或任何其他值为零的整数常量(。
[强调矿]
因此,整数常数0
是一个有效的空指针常数。
但请注意,这并不意味着所使用的硬件平台上的实际null值等于0
,它只意味着编译器接受0
作为系统相关null指针常量的别名。
此外,空指针总是"false",非空指针总是是"true",这就是为什么像if (ptr)
或if (!ptr)
这样的条件工作得很好。
我知道问题内容不同,但这怎么可能解释说使用NULL代替0是错误的,而
if(!ptr)
是真的吗?因为if(!ptr)
等价于if(!ptr)//ptr is a pointer
0(I假设这是正确的,不确定(。
if(!ptr)
在if
语句的语义上等价于if (!ptr != 0)
,在具有指针操作数的!
、!=
和==
运算符的语义上等效于if (ptr == 0)
。这是很好的一致性,但它并没有遵循你所知道的关于整数运算的任何内容。指针上的操作有自己的一组规则。
这正是回家的收获。由于值为零的整数常量(这是源代码构造(是空指针常量,因此根据定义将其与所有空指针值进行比较。这完全没有说明任何类型的空指针值的表示、NULL
宏扩展到的表达式的类型,或者通过将源代码中未表示为值为零的整数常量的任何特定空指针值转换为整数而产生的值。
NULL
是一个宏。它是"实现定义的空指针常量;"C17dr§7.19 3。
值为0的整数常量表达式,或转换为类型
void *
的此类表达式,称为空指针常量。C17dr§6.3.2.3 3
因此NULL
可能具有void *
、int
、long
、unsigned
、long long
等类型。
CCD_ 37是CCD_。
正常时。
分配:下面两个都将p,q
分配给某个空指针。
void *p = 0;
void *q = NULL;
代码比较:p==q
为真,因为所有空指针相等。所有空指针都不等于任何对象的地址。CCD_ 41和CCD_。
不正常时。
函数参数
NULL
的类型及其大小是实现定义的。
printf("%dn", 0); // OK - %d expects an int
printf("%dn", NULL); // Not OK, NULL could be long, void *, etc.
printf("%pn", NULL); // Not OK, NULL could be int, long, long long
printf("%pn", (void*) NULL); // OK - %p expects a void*
_Generic()
下面的结果是实现定义。
_Generic((NULL),
void *: "void *",
int: "int",
long: "long",
default: "TBD")
宏比较
以下操作导致我出现"错误:运算符'*'没有正确的操作数"。#if !0
很好。
#if !NULL
#error foo
#endif