打印
[牛人杂谈]

臭名昭著的空指针到底是什么?

[复制链接]
639|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wahahaheihei|  楼主 | 2016-9-11 22:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
语言定义中说明, 每一种指针类型都有一个特殊值—— “空指针” —— 它与
同类型的其它所有指针值都不相同, 它“与任何对象或函数的指针值都不相等”。
也就是说, 取地址操作符& 永远也不能得到空指针,  同样对malloc() 的成功调用
也不会返回空指针, 如果失败, malloc() 的确返回空指针, 这是空指针的典型用法:
表示“未分配” 或者“尚未指向任何地方” 的指针。

    空指针在概念上不同于未初始化的指针。空指针可以确保不指向任何对象或
函数; 而未初始化指针则可能指向任何地方。
    如上文所述, 每种指针类型都有一个空指针, 而不同类型的空指针的内部表示
可能不尽相同。尽管程序员不必知道内部值, 但编译器必须时刻明确需要那种空
指针,  以便在需要的时候加以区分

沙发
wahahaheihei|  楼主 | 2016-9-11 22:31 | 只看该作者
495个C语言问题.pdf (1.37 MB)



使用特权

评论回复
板凳
huangcunxiake| | 2016-9-12 09:18 | 只看该作者
空指针就是告诉系统,这个位置会放个指针。

使用特权

评论回复
地板
huangcunxiake| | 2016-9-12 09:19 | 只看该作者
对于空指针值,一般的文档中倾向于用 NULL 表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回NULL 和 返回 0 是完全等价的,因为 NULL 和 0 都表示 “null pointer”(空指针)。一句话, 空指针是什么,就是一个被赋值为0的指针,在没有被具体初始化之前,其值为0.

在uC/OS中普遍的用到了,对指针是否为空指针的判断,而没有把C语言中其中的语法知识讲解出来,很多同学对此理解有些含糊,趁着有时间,把其中的一些疑问及解答列举如下。若有错误请指正。
问题一: 什么是空指针常量(null pointer constant)?
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. (一个表示0值的整数常量,叫做空指针常量)
解释: 0、0L 、3 - 3(它们都是“integer constant expression”整数常量表达式)以及 (void*)0 等都是空指针常量(注意 (char*) 0 不叫空指针常量,只是一个空指针值)。
至于系统选取哪种形式作为空指针常量使用,则是实现相关的。
一般的 C 系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);
问题二: 什么是空指针(null pointer)?
If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function. ( 如果一个 空指针常量 赋给了一个有类型的指针变量,那么这个指针就叫空指针。它不指向任何的对象或者函数)
解释:如果 p 是一个指针变量,
若进行: p = 0;、p = 0L;、p = '\0';、p = 3 - 3;、p = 0 * 17; 中的任何一种赋值操作之后(对于 C 来说还可以是 p = (void*)0;)
p 都成为一个空指针,并且由系统保证空指针不指向任何实际的对象或者函数。 反过来说,任何对象或者函数的地址都不可能是空指针。
问题三: 什么是 NULL?
The macro( 宏)NULL is defined in <stddef.h> (and other headers) as a null pointer constant (NULL作为一个宏定义为一个空指针常量)
即 NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = NULL; 来使 p 成为一个空指针。
有些系统中这样来宏定义的
#define NULL 0
char *p = NULL;
问题四:空指针(null pointer)指向了内存的什么地方即空指针的内部实现?
标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0 地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见 C FAQ。
在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer 还是 nonzero null pointer,我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不同的。
问题5: 在实际的操作中 如何判断某个指针是不是空指针?
可以通过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。
指针变量 p 是空指针的判断: (假设 p 是一个指针变量,q 是一个同类型的空指针,要检查 p 是否是一个空指针)
if ( p == 0 )
if ( p == '\0' )
if ( p == 3 - 3 )
if ( p == NULL ) /* 使用 NULL 必须包含相应的标准库的头文件 */
if ( NULL == p )
if ( !p )
if ( p == q )
问题6: 可以定义自己的 NULL 的实现吗?
解释:If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.( NULL 是标准库中的一个符合上述条件的 reserved identifier (保留标识符)。所以,如果包含了相应的标准头文件而引入了 NULL 的话,则再在程序中重新定义 NULL 为不同的内容是非法的,其行为是未定义的
问题7:malloc 函数在分配内存失败时返回 0 还是 NULL?
解释: malloc 函数是标准 C 规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针):
If the space cannot be allocated, a null pointer is returned.
它指向系统内存具体哪个地方是由系统决定的,应用者不必去深究。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

213

主题

3022

帖子

12

粉丝