NULL、0和'\0'的位模式都为0。
1.在C语言标准中,空字符定义为“所有的位为0的字节称为空字符(null character)”。也就是说空字符是值为0的字符。空字符在表现上通常使用'\0'。
2.在我的环境中,NULL在stddef.h里的定义如下
#define NULL 0
但是标准允许将NULL定义为(void*)0,所以他们3个虽然数值都为0,但是类型一般是不一样的,如果NULL定义为(void*),那么使用NULL来结束字符串(char[len]=NULL)是错误的,尽管在某些运行环境中能跑起来。
int *p = 3;
int *p = 0;
第一句,在我的环境下会出现下面的警告waring:initialization makes pointer from integer from integer without a cast
第二句,这次没有警告
因为3无论怎么说都是int类型,指针和int类型是不一样的,所以编译器会提示警告。那为什么值为3时出现警告,而为0时却没有警告呢?简直匪夷所思!
这是因为在C语言中,“当常量0处于应该作为指针使用的上下文中时,它就作为空指针使用”。上面的例子中,因为接受赋值的对象为指针,编译器根据上下文判断“0应该最为指针使用”,所以将常数0作为空指针读取。
无论如何,编译器都会针对性的对待“需要将0作为指针进行处理的上下文”。这种情况下使用常量0作为空指针是合法的。因此,此时显示的将0强制转换成void*是没有意义的。但是在某些情况下,编译器可能会理解不了“应该将0作为指针进行处理的上下文”。
这些情况是:
1.没有原型声明的函数的参数
2.可变长参数函数中的可变部分的参数
ANSI C中,引入原型声明,只有在你确实作了原型声明时,编译器才知道你“想要传递指针”。
可是对于以printf为代表的可变长参数函数,其可变参数的类型编译器是不能理解的。另外,在可变长参数的函数中,还经常使用常量NULL来表示参数的结束,像execl调用。以上情况,简单的传递常量0,会降低可移植性。
因此当要传递空指针时,最好不使用上面的特性(貌似高级,但并不好用),而使用NULL宏来将0将强制转换成void*(当然你系统的NULL要为((void*)0), 要不就手动显示的进行强制转换)