深入理解空指针(C++)

空指针究竟指向了内存的哪个地方?

如果仅仅声明一个指针,而没有任何赋值,那么这个指针是野指针,它会指到任何位置,碰到异常操作,比如对只读区写操作,就会引起硬件中断产生core,也就是通常的段错误。

良好的编程风格是将指针永远都可控,也就是这个指针的地址,程序可控,通常,对于不使用或初始的指针都将其地址置为0,这是约定俗成的,就如同,我们经常使用的进制一样,你非用一个别人都不用的进制表示数,那也随你,只是别人觉得怪而已。再比如,用free释放完指针后,相信大家都会将指针置成NULL或0,就是为了再使用这个指针时,便于判断。指针的地址为0,操作起来就非常方便,比较位操作等,都可对应到机器码,这也就体现了“高级汇编”的美誉。用NULL宏,仅仅是为了可读性,编译器会进行优化的。

对于将NULL定义成某个地址,然后进行比较,相对NULL为0地址,然后比较,性质是相同的,在执行过程中,如果重新定义的地址为可操作,可能会对程序的逻辑流程产生影响。

===================================================================================

《C陷阱与缺陷》3.5节:

永远不能对空指针解引用!!!

如果将0赋给一个指针,绝对不能使用该指针指向的内容!!!

===================================================================================

空指针的简单描述:它“与任何对象或函数的指针值都不相等”。也就是说,取地址操作符 & 永远也不能得到空指针,同样对 malloc() 的成功调用也不会返回空指针,如果失败,malloc() 的确返回空指针,这是空指针的典型用法:表示 “未分配”或者 “尚未指向任何地方”的指针。

==================================================================================

空指针和未初始化的指针:空指针在概念上不同于未初始化的指针。空指针可以确保不指向任何对象或函数; 而未初始化指针则可能指向任何地方。

===================================================================================

空指针和 0

根据语言定义, 在指针上下文中的常数 0 会在编译时转换为空指针。

具体如下:

可以使用未加修饰的0                  需要显示的类型转换

初始化                               函数调用, 作用域内无原型

赋值                                 变参函数调用中的可变参数

比较

固定参数的函数调用且在作用域

内有原型

char *p = 0;                         execl("/bin/sh", "sh", "-c", "date", (char *)0);

if(p != 0)

-------------------------------------------------------------------------------------

注意:

if(p) 等价于 if(p != 0)。

这是一个比较上下文,因此编译器可以看出 0 实际上是一个空指针常数,并使用正确的空指针值。这里没有任何欺骗;编译器就是这样工作的,并为、二者生成完全一样的代码。

--*空指针的内部表达无关紧要。*--

===================================================================================

NULL和空指针

作为一种风格,很多人不愿意在程序中到处出现未加修饰的 0。因此定义了预处理宏 NULL (在 <stdio.h> 和其它几个头文件中) 为空指针常数,通常是 0 或者((void *)0) 。希望区别整数 0 和空指针 0 的人可以在需要空指针的地方使用NULL。

--*使用NULL只是一种风格习惯;*--

预处理器把所有的NULL都还原回0,而编译还是依照上文的描述处理指针上下文的 0。特别是,在函数调用的参数里,NULL之前 (正如在 0 之前) 的类型转换还是需要。C 程序员应该明白,在指针上下文中 NULL 和 0 是完全等价的,而未加修饰的 0 也完全可以接受。

--*任何使用 NULL (跟 0 相对) 的地方都应该看作一种温和的提示,是在使用指针。*--

程序员 (和编译器都) 不能依靠它来区别指针0和整数 0。特别是,不能在需要 ASCII 空字符 (NUL) 的地方用NULL。如果有必要, 提供你自己的定义#define NUL ’\0’。

===================================================================================

空指针的迷雾:空指针的内部 (或运行期) 表达形式,这可能并不是全零,而且对不用的指针类型可能不一样。真正的值只有编译器开发者才关心。C程序的作者永远看不到它们。

理清楚几个概念:

  1. 空指针,参见开头的定义,不同机器对于空指针的定义可能不同。
  2. 空指针常数,0 ,这个常数由编译器在运行阶段根据处理指针的上下文来转换为实际机器的空指针表达;
  3. NULL宏,它只是空指针成熟的一种风格定义,有好的提示使用的是指针。
  4. ASCII空字符(NULL),它的确是全零,但它和空指针除了在名称上以外,没有任何必然关系。
  5. “空串” (null string),它是内容为空的字符串 ("")。在 C 中使用空串这个术语可能令人困惑,因为空串包括空字符 (’\0’),但不包括空指针。

冲出迷雾:

冲出这些迷惘的一个好办法是想象 C 使用一个关键字作为空指针常数。编译器要么在源代码没有歧义的时候把空指针常数转成适当类型的空指针, 或者有歧义的时候发出提示。C 语言的空指针常数关键字是“0”,这在多数情况下都能正常工作,除了一个未加修饰的“0” 用在非指针上下文的时候,编译器把它生成整数 0 而不是发出错误信息,如果那个未加修饰的0是应该是空指针常数,那么生成的程序不行。

简单的方法:

  1. 当你在源码中需要空指针常数时, 用“0” 或“NULL”。
  2. 如果在函数调用中 “0” 或 “NULL” 用作参数, 把它转换成被调函数需要的指针类型(实际上这个2条件有点过于苛刻)。

深入理解空指针(C++)相关推荐

  1. 关于空指针(指针指向为NULL)和void类型的指针的理解

    正在学C,书上老说空指针,或者说void指针,对于我这样的生手来说,理解非常容易造成混淆,因为void这个单词的意思也是空,到底空指针的意思是指指向地址为空的类型呢,还是指void类型的指针呢 (1) ...

  2. 二叉树空指针个数的理解

    引言 二叉树在使用链式存储时,每一个结点都有两个指针,或者为空或者指向子结点. 二叉树所有空指针的个数为n+1是众所周知的事(n为二叉树结点个数),虽然不论哪种证明方法都仅仅是恒等式变形的结果,但去分 ...

  3. springboot 对象 空指针_C++ this指针的理解和作用

    C++ 程序到 C 程序的翻译  要想理解 C++ 的 this 指针,我们可以先把下面的 C++ 代码转换成 C 代码:C 语言是没有类定义 class 关键词,但是有跟 class 类似的定义,那 ...

  4. 理解C语言中的空指针和野指针

    在C语言中,指针是一个非常重要的概念,可以用于操作变量和数据结构.但是,指针也是很容易出错的地方.其中包括两种可能的错误:空指针和野指针. 空指针 空指针指代无效的地址,表示指针不指向内存中的任何一个 ...

  5. python 空指针_python 空指针

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 解压后依次执行以下命令安装 sdk. $ cd tencentcloud-sdk ...

  6. 常引用、常量指针、指针常量、指向常量的常指针、空指针与野指针解释

    1.一.基础知识 引用并非对象 引用必须初始化 引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起 类型要严格匹配 int &a = 10; //错误:引用类型的初始值必须是 ...

  7. 《C++应用程序性能优化::第五章动态内存管理》学习和理解

    <C++应用程序性能优化::第五章动态内存管理>学习和理解 说明:<C++应用程序性能优化> 作者:冯宏华等 2007年版. 2010.8.29 cs_wuyg@126.com ...

  8. 空指针,段错误,这场面试我栽倒在这里了!

    作者 | 李肖遥 来源 | 技术让梦想更伟大(ID:gh_f7effb2fbc1c) 面试官:满头的汗的,来面试的路一定很远吧? 还好还好,骑车不到俩小时 面试官:来先喝杯水,咱们面试不急,边喝边聊 ...

  9. 【java新】Optional pk 空指针

    空指针 Person person = people.find("John Smith"); person.doSomething(); 代码一 如果没有对person进行判空,那 ...

最新文章

  1. 互联网金融如何助力实体经济?
  2. 基于词典的正向最大匹配中文分词算法,能实现中英文数字混合分词
  3. js模拟栈---进制转化。十进制转任意进制进制,任意进制转十进制
  4. python爬虫用到的一些东西
  5. stm32f105vct6例程_STM32F107VCT6 107USB例程USB DEVICE例程
  6. 光流 | OpticalFlow博客资源
  7. 年均增长超200%的网易云信,如何向PaaS行业领跑者再进一步?
  8. Xamarin.Forms 5.0 来了
  9. Java Servlet教程– ULTIMATE指南(PDF下载)
  10. 前端学习(3188):ant-design的icon图标
  11. (十)DeepFaceLab:预包装的DIY深度伪造替代品
  12. 20190827:(leetcode习题)合并两个有序链表
  13. 一些编程习惯和问题记录--不定期更新
  14. LaTeX插入参考文献手把手教学 | BibTeX教程
  15. 79:企业CRM客户系统:登录模块开发(cookie和session以及登录态校验)
  16. 社交鼻祖人人网被卖 曾意气风发比肩Facebook 一代人的回忆终结了
  17. Redis基本数据类型和使用场景
  18. Linux ARM平台开发系列讲解(GMSL摄像头篇)1.2 MAX9296 GMSL链路配置
  19. 车载定位与轨迹服务系统
  20. 亚马逊广告授权流程说明

热门文章

  1. 多核程序设计的相关基础知识----以误差扩散算法为例
  2. 【leetcode】535. Encode and Decode TinyURL
  3. NYOJ 58 步数最少 【BFS】
  4. apache指定的网络名不再可用错误解决方法
  5. xcode Cornerstone 拷贝项目 提示框架头文件找不到的问题
  6. linux之man命令
  7. 在线正则表达式可视化工具
  8. CAD转换图片的小窍门
  9. GlusterFS分布式文件系统
  10. Ajax 浏览器跨域访问控制