转载于一位牛人:http://www.cnblogs.com/youxin/archive/2012/03/27/2420023.html

~(翻译是我自己理解翻译的,嘻嘻,难免会有错误还请多多指点)谢谢~。

先看下面一段代码输出什么:

#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";

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

//上面两句要一起理解。0可能会被作为大写字母O或者字符0.仅仅根据字体使用“O”看起来就像' 0 '很难分辨他们。

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

//'\0'是null字符用于中止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

在c++定义为0,在c中定义为(void *)0;为什么,参考:http://stackoverflow.com/questions/7016861/null-pointer-in-c-and-c

在探究的过程中找到下面的一个帖子。很是不错,COPY如下。
转载自:http://blog.chinaunix.net/u/18517/showart_309917.html


本文转自:http://bbs.chinaunix.net/viewthread.php?tid=544415&extra=&page=7
帖子里讨论了C语言中的空指针、空指针常量、NULL、0等概念及相互关系及区别。这里摘录whyglinux兄的总结。做个标签,呵呵^_^

  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,或这样的表达式类型void *,称为空指针常量

  2. 这里告诉我们:0、0L、'\0'、3 - 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。
  3. 什么是空指针(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.//如果一个空指针常量被转换为一个指针类型,产生的指针,称为空指针,保证比作一个指针指向任何对象或函数是不平等的。
    char *p=0;此时p就是一个空指针,不指向任何实际对象。
    因此,如果 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会有微秒的不同,当然也不是紧要了)

  4. 什么是 NULL?

    [6.3.2.3-Footnote] The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant//宏定义空< stddef.h >(和其他标题)作为一个空指针常量

    即 NULL 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = NULL; 来使 p 成为一个空指针。(tyc:很多系统中的实现:#define NULL (void*)0,与这里的“a null pointer constant”并不是完全一致的

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

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

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

  6. 如何判断一个指针是否是一个空指针?

    这可以通过与空指针常量或者其它的空指针的比较来实现(注意与空指针的内部表示无关)。例如,假设 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 )
    ...

  7. 可以用 memset 函数来得到一个空指针吗?

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

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

    是等价的吗?

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

  8. 可以定义自己的 NULL 的实现吗?兼答"NULL 的值可以是 1、2、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.//如果程序声明或定义一个标识符在一个上下文的保留(7.1.4所允许的以外),或将保留标识符定义为宏名称,其行为是未定义的。

    NULL 是标准库中的一个符合上述条件的 reserved identifier (保留标识符)。所以,如果包含了相应的标准头文件而引入了 NULL 的话,则再在程序中重新定义 NULL 为不同的内容是非法的,其行为是未定义的。也就是说,如果是符合标准的程序,其 NULL 的值只能是 0,不可能是除 0 之外的其它值,比如 1、2、3 等。

  9. 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

百度百科解释;

\0是C++中字符串的结尾标志,存储在字符串的结尾。比如char cha[5]表示可以放5个字符的字符串,由于c/c++中规定字符串的结尾标志为'\0',它虽然不计入串长,但要占内存空间,而一个汉字一般用两个字节表示,且c/c++中如一个数组cha[5],有5个变量,分别是 cha[0] , cha[1] , cha[2] , cha[3] , cha[4] , 所以cha[5]可以放5个字母或者放2个汉字(1个汉字占2个字节,1个字母占一个字节),cha[5]占5个字节内存空间.

  例如:

    char str[5];str[0]='a';str[1]='b';str[2]='c';str[3]='d';//str[4]='\0'; //abcd
    str[4]='e'; /*这样输出就是abcde和一堆乱码,甚至跳出系统错误,因为没有字符串结尾符*/printf("%s",str);

c语言NULL和0区别及NULL详解相关推荐

  1. c语言Null详解,c语言NULL和0区别及NULL详解(示例代码)

    先看下面一段代码输出什么: #include int main() { int *p=NULL; printf("%s",p); } 输出 ,单步调试可以看出执行int *p=NU ...

  2. C语言 NULL 和 0 区别 - C语言零基础入门教程

    目录 一.关于 NULL 定义 二.NULL 和 0 区别 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.关于 NULL 定义 NU ...

  3. C语言结构体与指针ppt,c语言指针和结构体:链表详解.ppt

    c语言指针和结构体:链表详解.ppt 1,第十一章 链表,2,例跳马.依下图将每一步跳马之后的位置x,y放到一个"结点"里,再用"链子穿起来",形成一条链,相邻 ...

  4. C语言结构体中定义函数指针详解

    C语言结构体中定义函数指针详解 结构体指针函数应用场景之一--驱动程序编写 结构体的一些基本用法 形式1:先定义结构体类型,再定义变量 形式2:在定义类型的同时定义变量 形式3:直接定义变量,用无名结 ...

  5. android ble蓝牙接收不到数据_Android蓝牙4.0 Ble读写数据详解 -2

    Android蓝牙4.0 Ble读写数据详解 -2 上一篇说了如何扫描与链接蓝牙 这篇文章讲讲与蓝牙的数据传输,与一些踩到的坑. 先介绍一款调试工具,专门调试Ble蓝牙的app.名字叫:nRF-Con ...

  6. c语言数据类型int的用法,C语言基本数据类型:整型(int)用法详解|C语言学习

    C语言基本数据类型:整型(int)用法详解 1. 整型 int C 语言提供了很多整数类型(整型),这些整型的区别在于它们的取值范围的大小,以及是否可以为负.int 是整型之一,一般被称为整型.以后, ...

  7. Android9.0 Launcher启动Activity详解(一)

    一.开始 Launcher中点击应用图标启动Activity,其开始方法是 public boolean startActivitySafely(View v, Intent intent, Item ...

  8. vue中如何调用ios摄像头_vue2.0调用摄像头步骤详解

    这次给大家带来vue2.0调用摄像头步骤详解,使用vue2.0调用摄像头的注意事项有哪些,下面就是实战案例,一起来看一下. 可以在github 上下载demo链接 vue组件代码 import {Ex ...

  9. c语言实现顺序表源程序,C语言实现静态顺序表的实例详解

    C语言实现静态顺序表的实例详解 线性表 定义一张顺序表也就是在内存中开辟一段连续的存储空间,并给它一个名字进行标识.只有定义了一个顺序表,才能利用该顺序表存放数据元素,也才能对该顺序表进行各种操作. ...

最新文章

  1. C#调用C++DLL传递结构体数组的终极解决方案
  2. 如何三步搭建一套声纹系统
  3. PyQt5 Python主对话框创建关于对话框源代码
  4. 一起学习C语言:C语言基本语法(一)
  5. leetcode刷题:1.无重复字符的最长字串
  6. 【Java编译】含package的类文件编译
  7. 发力多人在线游戏!PS5有望2020年E3展会亮相!
  8. 基于声波的手势识别技术
  9. Axure RP 9
  10. 《Python实用爬虫案例》练习8:获取搜狗搜索引擎微信文章
  11. 鸭子类型 Duck typing
  12. actionbar左上角的返回小图标
  13. 静态页面练习——京东商城登录页面
  14. 计算机xp bios密码设置方法,如何设置电脑的密码
  15. SCN Headroom过低问题处理
  16. 魔客仕高清HDMI摄像头USB工业相机
  17. 2021-2027全球及中国G Suit营销软件行业研究及十四五规划分析报告
  18. 这可能是我见过最好的 NumPy 图解教程!
  19. 企业常用服务器硬件介绍,以及部署RAIO,和部署LNMP
  20. Java AQS模型

热门文章

  1. Winning Design!: LEGO MINDSTORMS NXT 免积分下载
  2. linux 显示时钟 xming,【Linux】WSL+Xming实现gui显示
  3. 余生,不回头,不浪费,不将就
  4. 云主机与传统主机性能对比表
  5. foss测试_2018年FOSS十大法律发展
  6. ESP32学习笔记(41)——SNTP接口使用
  7. 技术前沿与经典文章10:信息论之父香农,20世纪伟大的科学家,一个理论改变了一个时代
  8. 30几岁,失业了很痛苦怎么办?
  9. 《从0到1上线微信小游戏》第十一节 接入微信小游戏广告
  10. JAVA学习笔记(五十七)- 常用设计模式