如果NULL和0作为空指针常数是等价的,如何选择
发布时间:2019-12-10
许多程序员认为在所有的指针上下文中都应该使用null, 以表明该值应该被看作指针。
另一些人则认为用一个宏来定义0, 只不过把事情搞得更复杂, 反而令人困惑。因而倾向于使用未加修饰的0。没有正确的答案。
c 程序员应该明白, 在指针上下文中null 和0 是完全等价的, 而未加修饰的0 也完全可以接受。任何使用null (跟0 相对) 的地方都应该看作一种温和的提示, 是在使用指针; 程序员(和编译器都) 不能依靠它来区别指针0 和整数0。
在需要其它类型的0 的时候, 即便它可能工作也不能使用null, 因为这样做
发出了错误的格式信息。(而且, ansi 允许把null 定义为((void *)0), 这在非指针的上下文中完全无效。特别是, 不能在需要ascii 空字符(nul) 的地方用null。如果有必要, 提供你自己的定义
#define nul ’\0’
拓展阅读:
对于空指针值,一般的文档中倾向于用 null 表示,而没有直接说成 0。但是我们应该清楚:对于指针类型来说,返回 null 和 返回 0 是完全等价的,因为 null 和 0 都表示 “null pointer”(空指针)。一句话, 空指针是什么,就是一个被赋值为0的指针,在没有被具体初始化之前,其值为0.
在uc/os中普遍的用到了,对指针是否为空指针的判断,而没有把c语言中其中的语法知识讲解出来,很多同学对此理解有些含糊,趁着有时间,把其中的一些疑问及解答列举如下。若有错误请指正。
问题一: 什么是空指针常量(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值的整数常量,叫做空指针常量)
解释: 0、0l 、3 - 3(它们都是“integer constant expression”整数常量表达式)以及 (void*)0 等都是空指针常量(注意 (char*) 0 不叫空指针常量,只是一个空指针值)。
至于系统选取哪种形式作为空指针常量使用,则是实现相关的。
一般的 c 系统选择 (void*)0 或者 0 的居多(也有个别的选择 0l);
问题二: 什么是空指针(null pointer)?
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. ( 如果一个 空指针常量 赋给了一个有类型的指针变量,那么这个指针就叫空指针。它不指向任何的对象或者函数)
解释:如果 p 是一个指针变量,
若进行: p = 0;、p = 0l;、p = '\0';、p = 3 - 3;、p = 0 * 17; 中的任何一种赋值操作之后(对于 c 来说还可以是 p = (void*)0;)
p 都成为一个空指针,并且由系统保证空指针不指向任何实际的对象或者函数。 反过来说,任何对象或者函数的地址都不可能是空指针。
问题三: 什么是 null?
the macro( 宏)null is defined in (and other headers) as a null pointer constant (null作为一个宏定义为一个空指针常量)
即 null 是一个标准规定的宏定义,用来表示空指针常量。因此,除了上面的各种赋值方式之外,还可以用 p = null; 来使 p 成为一个空指针。
有些系统中这样来宏定义的
#define null 0
char *p = null;
问题四:空指针(null pointer)指向了内存的什么地方即空指针的内部实现?
标准并没有对空指针指向内存中的什么地方这一个问题作出规定,也就是说用哪个具体的地址值(0x0 地址还是某一特定地址)表示空指针取决于系统的实现。我们常见的空指针一般指向 0 地址,即空指针的内部用全 0 来表示(zero null pointer,零空指针);也有一些系统用一些特殊的地址值或者特殊的方式表示空指针(nonzero null pointer,非零空指针),具体请参见 c faq。
在实际编程中不需要了解在我们的系统上空指针到底是一个 zero null pointer 还是 nonzero null pointer,我们只需要了解一个指针是否是空指针就可以了——编译器会自动实现其中的转换,为我们屏蔽其中的实现细节。注意:不要把空指针的内部表示等同于整数 0 的对象表示——如上所述,有时它们是不同的。