C语言: 空指针和空指针常量

  1. 什么是空指针常量(null pointer constant)?

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

    这里告诉咱们:0、0L、'\0'、3 - 三、0 * 17 (它们都是“integer constant expression”)以及 (void*)0 (tyc: 我以为(void*)0应该算是一个空指针吧,更恰当一点)等都是空指针常量(注意 (char*) 0 不叫空指针常量,只是一个空指针值)。至于系统选取哪一种形式做为空指针常量使用,则是实现相关的。通常的 C 系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);至于 C++ 系统,因为存在严格的类型转化的要求,void* 不能象 C 中那样自由转换为其它指针类型,因此一般选 0 做为空指针常量(tyc: C++标准推荐),而不选择 (void*)0。

  2. 什么是空指针(null pointer)?

    [6.3.2.3-3] 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 都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来讲,任何对象或者函数的地址都不多是空指针。(tyc: 好比这里的(void*)0就是一个空指针。把它理解为null pointer仍是null pointer constant会有微秒的不一样,固然也不是紧要了)

  3. 什么是 NULL?

    [6.3.2.3-Footnote] The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant

    即 NULL 是一个标准规定的宏定义,用来表示空指针常量。所以,除了上面的各类赋值方式以外,还能够用 p = NULL; 来使 p 成为一个空指针。(tyc:不少系统中的实现:#define NULL (void*)0,与这里的“a null pointer constant”并非彻底一致的)

  4. 空指针(null pointer)指向了内存的什么地方(空指针的内部实现)?

    标准并无对空指针指向内存中的什么地方这一个问题做出规定,也就是说用哪一个具体的地址值(0x0 地址仍是某一特定地址)表示空指针取决于系统的实现。咱们常见的空指针通常指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见
    C FAQ

    幸运的是,在实际编程中不须要了解在咱们的系统上空指针究竟是一个 zero null pointer 仍是 nonzero null pointer,咱们只须要了解一个指针是不是空指针就能够了——编译器会自动实现其中的转换,为咱们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不一样的。

  5. 如何判断一个指针是不是一个空指针?

    这能够经过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。例如,假设 p 是一个指针变量,q 是一个同类型的空指针,要检查 p 是不是一个空指针,能够采用下列任意形式之一——它们在实现的功能上都是等价的,所不一样的只是风格的差异。

    指针变量 p 是空指针的判断:
    if ( p == 0 )
    if ( p == '\0' )
    if ( p == 3 - 3 )
    if ( p == NULL )  /* 使用 NULL 必须包含相应的标准库的头文件 */
    if ( NULL == p )
    if ( !p )
    if ( 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. 能够用 memset 函数来获得一个空指针吗?

    这个问题等同于:若是 p 是一个指针变量,那么

    memset( &p, 0, sizeof(p) ); 和 p = 0;

    是等价的吗?

    答案是否认的,虽然在大多数系统上是等价的,可是由于有的系统存在着“非零空指针” (nonzero null pointer),因此这时二者不等价。因为这个缘由,要注意当想将指针设置为空指针的时候不该该使用 memset,而应该用空指针常量或空指针对指针变量赋值或者初始化的方法。

  7. 能够定义本身的 NULL 的实现吗?兼答"NULL 的值能够是 一、二、3 等值吗?"相似问题

    [7.1.3-2] 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 为不一样的内容是非法的,其行为是未定义的。也就是说,若是是符合标准的程序,其 NULL 的值只能是 0,不多是除 0 以外的其它值,好比 一、二、3 等。

  8. malloc 函数在分配内存失败时返回 0 仍是 NULL?

    malloc 函数是标准 C 规定的库函数。在标准中明确规定了在其内存分配失败时返回的是一个 “null pointer”(空指针):

    [7.20.3-1] If the space cannot be allocated, a null pointer is returned.

    对于空指针值,通常的文档(好比 man)中倾向于用 NULL 表示,而没有直接说成 0。可是咱们应该清楚:对于指针类型来讲,返回 NULL 和 返回 0 是彻底等价的,由于 NULL 和 0 都表示 “null pointer”(空指针)。(tyc:通常系统中手册中都返回NULL,那咱们就用NULL吧)
另外,附C FAQ上关于null pointer的解释: C FAQ:null pointer
相关文章
相关标签/搜索