概述
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的区别的全部内容,希望文章能够帮你解决64位环境0和NULL的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复