在C语言中,各种零值之间似乎存在差异——NULL、NUL和0。

我知道ASCII字符“0”的值为48或0x30。

NULL指针通常定义为:

#define NULL 0

Or

#define NULL (void *)0

此外,还有NUL字符“\0”,它的值似乎也是0。

是否存在这三个值不能相等的情况?

在64位系统上也是这样吗?


当前回答

一篇帮助我开始学习C语言的好文章(摘自Linden的Expert C Programming)

一个l为空,两个l为空

记住这个小押韵来回忆指针和ASCII零的正确术语:

The one "l" NUL ends an ASCII string,

The two "l" NULL points to no thing.

Apologies to Ogden Nash, but the three "l" nulll means check your spelling. 

位模式为0的ASCII字符称为“NUL”。 特殊的指针值意味着指针不指向任何地方是“NULL”。 这两个词在意思上是不可互换的。

其他回答

在ASCII表中,值为0x00的字节是称为NUL或NULL的特殊字符。在C语言中,因为你不应该在源代码中嵌入控制字符,所以这是用C字符串表示的,带有一个转义0,即\0。

但是一个真NULL不是一个值。它是一个值的缺失。对于指针来说,这意味着指针没有可指向的对象。在数据库中,它意味着字段中没有值(这与字段为空白、0或填充空格不同)。

给定的系统或数据库文件格式用来表示NULL的实际值不一定是0x00。

似乎很多人误解了NULL、'\0'和0之间的区别。为了避免重复之前说过的话,我来解释一下:

int类型的值为0的常量表达式,或该类型的表达式,转换为void *类型是空指针常量,如果转换为指针则成为空指针。该标准保证与指向任何对象或函数的任何指针的比较不相等。

NULL是一个宏,定义为空指针常量。

\0是一个用于表示空字符的结构,用于结束字符串。

空字符是一个所有位都设置为0的字节。

NULL不能保证为0——它的确切值取决于体系结构。大多数主流架构将其定义为(void*)0。

'\0'将总是等于0,因为这是字节0在字符字面值中编码的方式。

我不记得C编译器是否被要求使用ASCII——如果不是,'0'可能并不总是等于48。无论如何,除非您在非常晦涩的系统上工作,否则您不太可能遇到使用像EBCDIC这样的替代字符集的系统。

各种类型的大小在64位系统上有所不同,但整数值是相同的。


一些评论者表示怀疑NULL等于0,但不是0。下面是一个示例程序,以及在这样一个系统上的预期输出:

#include <stdio.h>

int main () {
    size_t ii;
    int *ptr = NULL;
    unsigned long *null_value = (unsigned long *)&ptr;
    if (NULL == 0) {
        printf ("NULL == 0\n"); }
    printf ("NULL = 0x");
    for (ii = 0; ii < sizeof (ptr); ii++) {
        printf ("%02X", null_value[ii]); }
    printf ("\n");
    return 0;
}

该程序可以输出:

NULL == 0
NULL = 0x00000001

如果NULL和0是等价的空指针常数,我应该使用哪个?在C常见问题解答列表中也解决了这个问题:

C programmers must understand that NULL and 0 are interchangeable in pointer contexts, and that an uncast 0 is perfectly acceptable. Any usage of NULL (as opposed to 0) should be considered a gentle reminder that a pointer is involved; programmers should not depend on it (either for their own understanding or the compiler's) for distinguishing pointer 0's from integer 0's. It is only in pointer contexts that NULL and 0 are equivalent. NULL should not be used when another kind of 0 is required, even though it might work, because doing so sends the wrong stylistic message. (Furthermore, ANSI allows the definition of NULL to be ((void *)0), which will not work at all in non-pointer contexts.) In particular, do not use NULL when the ASCII null character (NUL) is desired. Provide your own definition

#define NUL '\0'

如果你一定要的话。

NULL, ' \0 '和0之间的区别是什么

“空字符(NUL)”是最容易排除的。'\0'是字符字面量。 在C语言中,它被实现为int,因此,它与0相同,它是INT_TYPE_SIZE。在c++中,字符字面值被实现为char,即1字节。这通常不同于NULL或0。

接下来,NULL是一个指针值,指定变量不指向任何地址空间。撇开它通常实现为零的事实不谈,它必须能够表达体系结构的完整地址空间。因此,在32位体系结构上,NULL(可能)是4字节的,而在64位体系结构上是8字节的。这取决于C的实现。

最后,字面值0的类型为int,大小为INT_TYPE_SIZE。INT_TYPE_SIZE的默认值可能根据体系结构而不同。

苹果写道:

Mac OS X使用的64位数据模型被称为“LP64”。这是Sun和SGI的其他64位UNIX系统以及64位Linux所使用的通用数据模型。LP64数据模型定义的基元类型如下: int是32位的 long是64位的 long-long也是64位的 指针是64位的

维基百科64位:

微软的vc++编译器使用LLP64模型。

64-bit data models
Data model short int long  long long pointers Sample operating systems
LLP64      16    32  32    64        64       Microsoft Win64 (X64/IA64)
LP64       16    32  64    64        64       Most Unix and Unix-like systems (Solaris, Linux, etc.)
ILP64      16    64  64    64        64       HAL
SILP64     64    64  64    64        64       ?

编辑: 增加了更多的字符文字。

#include <stdio.h>

int main(void) {
    printf("%d", sizeof('\0'));
    return 0;
}

上面的代码在gcc上返回4,在g++上返回1。