0 & NULL

在C语言中将值为0的指针作为NULL,NULL通常被定义为0或((void *)0);

有很多应该使用NULL的地方写0代替的程序,通常这样的写法也不会发生问题,如:

char *p = 0;

if (p != 0) ...

此时p为char *,进行运算前,会将操作数类型转换为与之有互换性的某个类型上,所以默认int型的0转换为char *型的NULL,这样一来,下面的书写方法也没有问题:

if (p)

在此时if会用布尔值来判断,用表达式的布尔值是否为0来判断。如下所示:

if (p != 0)

相反的条件

if (!p)

也跟

if(p == 0)

等价

象这样在多数情况下,用0代替NULL的处理方式也可以。但是也存在不通用的地方。

0和NULL不同的情况

如前所述,NULL并不是int型的0值,而是指针型的0值(值为0的指针);也就是说编译器必须要明白是用指针理性来解释,

在x86那样的ILP32环境中由于int long指针都是32位,所以int型的0可以等同于指针的NULL。但在IA64那样的LP64环境中int仍然是32位的,但long和指针都是64位的,int的0便不等同于NULL了。使用可变长参数时,这个问题很明显。示例代码:

struct s *foo(const char *name, ...)
{va_list va;struct s *sp;char *p;va_start(va, fmt);sp = (struct s *)malloc(*sp);if (!sp) {return 0;}memset(sp, 0,sizeof(*sp));set_name(sp, name);while ((p = va_arg(va, char *))) {set_item(sp, p);}return sp;
}...
sp = foo("foo", "bar", 0);
...

这里的foo()是取得可变长参数后,利用name这个名称和剩下的参数表初始化item结构体的函数。这个代码在LP64环境下不能正常运行。

调用foo("foo", "bar", 0)之后,参数会像下面这样 堆积在栈上:

为0的int

指向"bar"的const char *

指向"foo"的const char *

在foo()运行时,形参const char *name指向第一个参数"foo", 其他变参通过va_list来访问,在foo()中通过如下形式取va_list内容:

p = va_arg(va, char *);

也就是参数作为char *来取出,第一个是指向"bar"的指针,所以没问题。而第二个变参传的是int型(32位)的0,但读取时是按64位的char *来取的,多读取了4字节为初始化的内存数据,如果这四个字节不是全0,而导致进入下一次while循环,会发生什么后果呢?

这就是将0和NULL混用而导致的bug,正确调用foo()的方法:

sp = foo("foo", "bar", NULL);

也有自己编程使用类似函数的情况,例如:使用类似机制的execl(3)时,必须用NULL来终止参数列表(见man手册提示):

int execl(const char *path, const char *arg, .../*, (char *)0*/);

字面量 0 ,是int型,在64位系统里是32位。
宏 NULL, 定义为((void*)0),在64位系统里是64位。

在foo函数定义之后使用该函数,或在使用foo函数之前声明一下foo函数,编译器就会自动将int型的0转为void*型的NULL。

如果没有定义或声明foo函数就直接使用foo函数,编译器会根据你传入的参数产生一个隐含的声明。
调用foo("foo", "bar", 0),编译器会认为你的函数声明为int foo(char*, char*, int),并且根据此声明压栈,共20字节。

而函数实际定义为foo(char*, char *, void*),函数会把传入的第三个参数当做void*解析,16~19字节是整数0,20~23字节数据未定义,函数会取到一个错误的指针(在big-endian系统里,指针低位部分为0,高位部分未定义,即0x********00000000;在little-endian系统里,指针低位部分未定义,高位部分位0,即0x00000000********)

C++中还可以用nullptr。

转自:https://www.phpfans.net/ask/MTEwNjM3OQ.html

64位环境0和NULL的区别相关推荐

  1. 64位环境编译DiskSim 4.0

    DiskSim没有64位版本,即使侥幸编译成功,运行时也会出现段错误.因此需要对源码进行一些修改,才能在64位环境使用,下文总结了在Ubuntu 64bit上编译DiskSim的全过程. 1.安装bi ...

  2. [思考]-32位的应用程序和64位的应用程序有什么区别

    文章目录 1.32位的应用程序和64位的应用程序有什么区别 2.在aarch64的linux os中,是否同时支持运行32位app和64位app ★★★ 链接 : 个人博客导读首页-点击此处 ★★★ ...

  3. 64位环境中使用SQL查询excel的方式解决

    --64位环境中使用SQL查询excel的方式 环境: OS:Windows Server 2008 R2 Enterprise MSSQL:Microsoft SQL Server 2008 R2 ...

  4. win7 64位系统与32系统的区别

    http://www.qiankoo.com/thread-870-1-1.html 不管你是菜鸟还是老鸟应该都听说过,或者接触过32位系统与64位系统. 但你了解64位系统与32位系统有什么区别吗? ...

  5. oracle连接超时 pb,pb9 在win7 64位环境上连接oracle10g出错

    pb9 在win7 64位环境下连接oracle10g出错我在本机重装了操作系统,操作系统是win7 64位的系统,数据库是oracle 10g,我用plsql.sql plus等连接本机数据库均能正 ...

  6. 【笔试题】C语言结构体中,不同的数据类型在32位和64位下所占字节的区别

    题目 如下C程序,在64位处理器上运行后sz的值是什么? struct st {int *p;int i;char a; }; int sz=sizeof(struct st); 答案 16 解析 考 ...

  7. 观看实验中微型计算机虚拟拆装演示,虚拟仿真实验 北斗一号微机原理虚拟仿真实验系统64位 v3.0...

    下面我们对虚拟仿真实验 北斗一号微机原理虚拟仿真实验系统64位 v3.0文件阐述相关使用资料和虚拟仿真实验 北斗一号微机原理虚拟仿真实验系统64位 v3.0文件的更新信息. 虚拟仿真实验 北斗一号微机 ...

  8. python2.7安装教程win7_win7 64位环境下,为python2.7 安装pip

    第一步: 安装python并配置好环境变量 第二步: 下载setuptools源码setuptools-38.5.1.zip,地址:https://pypi.python.org/pypi/setup ...

  9. android 版本号 7.0 O,微信全面上线64位7.0.9版本:运行速度更快,你更新了吗?(附下载)...

    微信全面上线64位7.0.9版本:运行速度更快,你更新了吗?(附下载) 2019-11-30 17:53:48 3点赞 1收藏 0评论 微信安卓正式版最近又双叒叕更新啦!最新的版本号是7.0.9,上一 ...

最新文章

  1. Java访问权限(详尽版)
  2. Redis 16 个常见使用场景
  3. 《Swift 权威指南》——导读
  4. 当 .NET 5 遇上OpenTelemetry,会碰撞出怎样的火花?
  5. 使用std::thread线程相关函数,-static静态编译的程序运行时的一些常见错误
  6. 接雨水12 · Trapping Rain Water12
  7. 《强化学习》中的第11章:基于函数逼近的离轨策略方法
  8. ??? Error using == Inner matrix dimensions must agree.
  9. 建模步骤_数学建模的基本步骤
  10. 20.10 for循环 20.11/20.12 while循环 20.13 break跳出循环 20.14 continue结束本次循环 20.15 exit退出整个脚本...
  11. 《涂抹Oracle—三思笔记之一步一步学Oracle》看书笔记(第一章)
  12. 分享 上班族兼职项目——存着慢慢看很有用
  13. ASP.NET全套视频教程
  14. Ocelot.Authorization.Middleware.AuthorizationMiddleware[0] requestId: 0HMJ300E5APNA:00000002...
  15. 经典计算机书籍-自制系列
  16. 基于NT98530的多目VR摄像机方案,多sensor同步,多sensor防抖,PTP校时,实景SLAM数字孪生的最佳搭档。
  17. 世界著名设计公司-网址介绍
  18. 2022支付宝集五福攻略,一天20张不是事
  19. Spring 事务管理
  20. 一、CameraService启动流程

热门文章

  1. '#selector' does not refer to an '@objc' method,No method declared with Objective-C selector 'compos
  2. 单片机原理及其应用——单片机控制8只发光二极管交替闪烁
  3. java获取进程端口_查看进程的端口号
  4. LVM逻辑卷 (概述lvm,管理卷组 物理卷 逻辑卷,磁盘配额)
  5. 高效多用的群集-Haproxy搭建Web集群
  6. android dialog 结构,Android 原生Dialog实现
  7. python网络编程能做什么_python网络编程——什么是socket?
  8. php连接mysql 5.1.73_安装php环境(php5.4.44+mysql5.1.73+IIS)
  9. c++ asc chr 函数_15万怎么选?丰田CHR、本田XRV谁档次高?车主说了心里话
  10. 计算机英语句子缩略,根据汉语意思完成英语句子,每空一词(含缩略形式)。 【1】-咋考网...