您的位置:首页 > 编程语言 > C语言/C++

c语言NULL和0区别及NULL详解

2016-06-12 16:21 281 查看
首先,我们测试一个程序:

#include<stdo.h>
int main()
{
int *p=NULL;
printf("%s",p);

}


输出<null> ,单步调试可以看出执行int *p=NULL,p的值为0x00000000,可以看出,NULL在实际底层调用中就是0; 

在C语言中,

NULL和0的值都是一样的,但是为了目的和用途及容易识别的原因,NULL用于指针和对象,0用于数值

对于字符串的结尾,使用'\0',它的值也是0,但是让人一看就知道这是字符串的结尾,不是指针,也不是普通的数值

在不同的系统中,

NULL并非总是和0等同,NULL仅仅代表空值,也就是指向一个不被使用的地址,在大多数系统中,都将0作为不被

使用的地址,所以就有了类似这样的定义

#define NULL 0

但并非总是如此,也有些系统不将0地址作为NULL,而是用其他的地址,所以说,千万别将NULL和0等价起来,特别是在一些跨平台的代码中,这更是将给你带来灾难。

解释:问 0 '0' '\0' "\0"

To me, when doing C/C++:  

0 would digit zero, that is, a numerical value.  0救赎数值0,常量值

'0' could be the character capital oh or the character zero. For example: char word[10] = "Oxford"; char number[10] = "01234";

‘0’可能是字符首部或者字符。例如,  char word[10] = "Oxford"; char number[10] = "01234";

Depending on typeface used 'O' may look exactly like '0' making it difficult to tell them apart out of context.

根据字体用“O”看起来像“0”,很难分辨出背景

'\0' is the null character used to terminate strings in C/C++.

‘\0’在C/C++中是空指针

"\0" is an empty string.

“\0”是一个空字符串

NULL在stdio.h中定义:


#if !defined(NULL) && defined(__NEEDS_NULL)
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif


问题:

1、什么是空指针常量 (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,或这样的表达式转换为 void*,被称为空指针常量

这里告诉我们:0、0L、‘\0’、3-3、0*10 以及(void*)0 等都是空指针常量(注意
(char*) 0 不叫空指针常量,只是一个空指针值)。至于系统选取哪种形式作为空指针常量使用,则是实现相关的。一般的 C 系统选择 (void*)0 或者 0 的居多(也有个别的选择 0L);至于 C++ 系统,由于存在严格的类型转化的要求,void* 不能象 C 中那样自由转换为其它指针类型,所以通常选 0 作为空指针常量,而不选择 (void*)0。

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

char *p=0;此时p就是一个空指针,不指向任何实际对象。

因此,如果 p 是一个指针变量,则 p = 0;、p = 0L;、p = '\0';、p = 3 - 3;、p = 0 * 10; 中的任何一种赋值操作之后(对于 C 来说还可以是 p = (void*)0;), p 都成为一个空指针,由系统保证空指针不指向任何实际的对象或者函数。反过来说,任何对象或者函数的地址都不可能是空指针。

3、什么是NULL?

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

宏观的NULL定义在stddef.h或者其他头文件里,作为空指针常量

即 NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = NULL; 来使 p 成为一个空指针。

4、空指针指向了内存哪个地方(空指针的内部实现)?

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

幸运的是,在实际编程中不需要了解在我们的系统上空指针到底是一个 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 的值可以是 1、2、3 等值吗?"类似问题

NULL 是标准库中的一个符合上述条件的 reserved identifier (保留标识符)。所以,如果包含了相应的标准头文件

而引入了 NULL 的话,则再在程序中重新定义 NULL 为不同的内容是非法的,其行为是未定义的。也就是说,如果

是符合标准的程序,其 NULL 的值只能是 0,不可能是除 0 之外的其它值,比如 1、2、3 等。

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

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

对于空指针值,一般的文档(比如 man)中倾向于用 NULL 表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回 NULL 和 返回 0 是完全等价的,因为 NULL 和 0 都表示 “null pointer”(空指针)。

转自:http://www.cnblogs.com/youxin/archive/2012/03/27/2420023.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: