为啥指针可以为NULL
Posted
技术标签:
【中文标题】为啥指针可以为NULL【英文标题】:Why can pointers be NULL为什么指针可以为NULL 【发布时间】:2017-11-16 01:01:45 【问题描述】:在 C 或 C++ 中,NULL 不只是常量整数 0 吗?如果它是一个常量整数,为什么我们允许分配一些指向值 NULL 的指针?编译器不会说这两种类型不匹配吗?
【问题讨论】:
【参考方案1】:常量0
的解释取决于上下文。如果在需要数字的上下文中使用它,则它是数字零。如果在需要指针的上下文中使用它,则将其视为空指针。所以如果你有代码:
int n = 0; // assigns zero
int *p = 0; // assigns null pointer
somefunc((char *)0); // passes null pointer to the function
在 C 中,允许宏 NULL
扩展为整数常量 0
或此类常量转换为 void *
。在 C++ pre-11 中,它可以扩展为计算结果为 0
的整数常量。在 C++-11 中,它可以扩展为具有值 0
或类型为 std::nullptr_t
的纯右值(例如 nullptr
)的整数文字。
有关 C++ 说明,请参阅 http://en.cppreference.com/w/cpp/types/NULL,有关 C 说明,请参阅 http://en.cppreference.com/w/c/types/NULL。
【讨论】:
在 C++ 中,允许扩展为任何空指针常量,包括nullptr
。
@BaummitAugen 但在 C++ 中它不允许为 (void*)0
,因为 C++ 不像 C 那样对 void*
进行隐式转换。
问题是关于NULL的定义。
@MarkRansom 当然,我并没有对此提出异议。
en.cppreference.com/w/cpp/types/NULL 表示它必须是整数文字或 std::nullptr_t
类型的值。 (void*)0
是其中之一吗?【参考方案2】:
有两个问题:
一个类型可以有一个“特殊的”、带外的、异常值。例如,浮点数的值为NaN
。并且指针有一个特殊的非有效指针值,即空指针。
空指针的名称是什么?在 C 中,无论好坏,它的名字都是0
。 (如果它的名称是一个单独的关键字,如 null
或 nil
,它会避免各种混淆,但语言定义不是这样出来的。)
但是,是的,您是对的,将常量 0
分配给指针变量的能力是一种特殊情况,体现在语言定义中。
【讨论】:
那么 nullptr 真的只是内存位置“0”吗?而且,我的教授说,对于返回指向数组中元素的指针的函数,如果不满足某些条件,越来越多的人将指针分配给数组中最后一个元素之后的元素,而不是分配指针为 NULL 或 nullptr。这是真的吗? @HowardWang 不一定是内存位置 0。但是对于您可以想象的每个后续问题,请参阅C FAQ list。 @HowardWang 现代 C++ 使用在概念上类似于指针的迭代器。所有标准库函数都使用两个迭代器来定义一个范围,第二个迭代器指向最后一个有效元素之后的一个。从这些函数返回“未找到”值意味着返回结束迭代器。这可能会对指针的使用方式产生一些影响。【参考方案3】:6.3.2.3 指针 ... 3 值为 0 的整型常量表达式,或这种类型转换为void *
的表达式,称为 空指针常量。66) 如果空指针常量是转换为指针类型后,生成的指针称为空指针,保证与指向任何对象或函数的指针不相等。
66) 宏 NULL 在(和其他头文件)中定义为空指针常量;见 7.19。
C 2011 online draft
指针上下文中的文字0
由编译器特殊处理,并被理解为空指针常量。在您的源代码上下文中,它的行为类似于任何其他零值表达式。
但是,一旦您的代码被转换为机器码,所有出现的空指针常量都将被底层平台用来表示定义明确的 invalid 指针值的任何值替换,无论是0
或 0xFFFFFFFF
或 0xDEADBEEF
。
【讨论】:
虽然标准允许空指针在物理上并非全为零,但我不知道有任何架构以这种方式工作。使用零的字面位模式更容易、更有效。 @MarkRansom -- 我听说过带有空指针的古代系统的故事,这些空指针并非全为零。以上是关于为啥指针可以为NULL的主要内容,如果未能解决你的问题,请参考以下文章
为啥free函数不在释放内存后,将指针置NULL,野指针有啥用
在C语言编程中,为啥要将指针变量在开始的时候赋值为NULL?