0和0之間的區別是什么?

[英]What is the difference between NULL, '\0' and 0


In C, there appear to be differences between various values of zero -- NULL, NUL and 0.

在C中,不同值之間似乎存在差異——NULL, NUL和0。

I know that the ASCII character '0' evaluates to 48 or 0x30.

我知道ASCII字符'0'的值是48或0x30。

The NULL pointer is usually defined as:

空指針通常定義為:

#define NULL 0

Or

#define NULL (void *)0

In addition, there is the NUL character '\0' which seems to evaluate to 0 as well.

此外,還有NUL字符'\0',它似乎也值為0。

Are there times when these three values can not be equal?

是否存在這三個值不相等的時刻?

Is this also true on 64 bit systems?

在64位系統上也是這樣嗎?

11 个解决方案

#1


280  

Note: This answer applies to the C language, not C++.

注意:這個答案適用於C語言,而不是c++。


Null Pointers

The integer constant literal 0 has different meanings depending upon the context in which it's used. In all cases, it is still an integer constant with the value 0, it is just described in different ways.

integer常量literal 0根據使用的上下文有不同的含義。在所有情況下,它仍然是一個值為0的整數常量,它只是用不同的方式描述。

If a pointer is being compared to the constant literal 0, then this is a check to see if the pointer is a null pointer. This 0 is then referred to as a null pointer constant. The C standard defines that 0 cast to the type void * is both a null pointer and a null pointer constant.

如果將指針與常量文字0進行比較,那么這是一個檢查指針是否為空指針的檢查。這個0被稱為空指針常量。C標准定義了0轉換到類型void *既是空指針,也是空指針常量。

Additionally, to help readability, the macro NULL is provided in the header file stddef.h. Depending upon your compiler it might be possible to #undef NULL and redefine it to something wacky.

此外,為了幫助可讀性,在頭文件stddef.h中提供了宏NULL。根據您的編譯器,可以將undef NULL重新定義為古怪的東西。

Therefore, here are some valid ways to check for a null pointer:

因此,這里有一些有效的方法來檢查空指針:

if (pointer == NULL)

NULL is defined to compare equal to a null pointer. It is implementation defined what the actual definition of NULL is, as long as it is a valid null pointer constant.

NULL被定義為與空指針比較。它是實現定義了NULL的實際定義,只要它是有效的空指針常量。

if (pointer == 0)

0 is another representation of the null pointer constant.

0是空指針常量的另一個表示。

if (!pointer)

This if statement implicitly checks "is not 0", so we reverse that to mean "is 0".

如果語句隱式檢查“不是0”,那么我們將其反向為“為0”。

The following are INVALID ways to check for a null pointer:

以下是檢查空指針的無效方法:

int mynull = 0;
<some code>
if (pointer == mynull)

To the compiler this is not a check for a null pointer, but an equality check on two variables. This might work if mynull never changes in the code and the compiler optimizations constant fold the 0 into the if statement, but this is not guaranteed and the compiler has to produce at least one diagnostic message (warning or error) according to the C Standard.

對於編譯器,這不是一個空指針的檢查,而是兩個變量的等式檢查。如果mynull在代碼中沒有變化,編譯器優化常數將0在if語句中加入0,這可能會起作用,但這並沒有保證,而且編譯器必須根據C標准生成至少一個診斷消息(警告或錯誤)。

Note that what is a null pointer in the C language. It does not matter on the underlying architecture. If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.

注意,在C語言中什么是空指針。它對底層架構沒有影響。如果底層架構的空指針值定義為地址0xDEADBEEF,那么就由編譯器來處理這個問題。

As such, even on this funny architecture, the following ways are still valid ways to check for a null pointer:

因此,即使在這個有趣的架構中,以下方法仍然是檢查空指針的有效方法:

if (!pointer)
if (pointer == NULL)
if (pointer == 0)

The following are INVALID ways to check for a null pointer:

以下是檢查空指針的無效方法:

#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)

as these are seen by a compiler as normal comparisons.

因為這些被編譯器看作是正常的比較。

Null Characters

'\0' is defined to be a null character - that is a character with all bits set to zero. This has nothing to do with pointers. However you may see something similar to this code:

“\0”被定義為一個空字符——這是一個所有位都設置為零的字符。這與指針無關。不過,您可能會看到類似的代碼:

if (!*string_pointer)

checks if the string pointer is pointing at a null character

檢查字符串指針是否指向一個空字符。

if (*string_pointer)

checks if the string pointer is pointing at a non-null character

檢查字符串指針是否指向非空字符。

Don't get these confused with null pointers. Just because the bit representation is the same, and this allows for some convenient cross over cases, they are not really the same thing.

不要把這些與空指針混淆。僅僅因為位表示是相同的,這允許一些方便的交叉,它們實際上不是一回事。

Additionally, '\0' is (like all character literals) an integer constant, in this case with the value zero. So '\0' is completely equivalent to an unadorned 0 integer constant - the only difference is in the intent that it conveys to a human reader ("I'm using this as a null character.").

另外,'\0'是(像所有字符文字一樣)一個整數常量,在這個例子中值為零。因此,“\0”完全等價於一個不加修飾的0整數常量——惟一的區別在於它向一個人讀者傳達的意圖(“我用這個作為空字符”)。

References

See Question 5.3 of the comp.lang.c FAQ for more. See this pdf for the C standard. Check out sections 6.3.2.3 Pointers, paragraph 3.

參見問題5.3。c FAQ。請參閱此pdf的C標准。請參閱第6.3.2.3節指示,第3段。

#2


27  

It appears that a number of people misunderstand what the differences between NULL, '\0' and 0 are. So, to explain, and in attempt to avoid repeating things said earlier:

似乎有許多人誤解了NULL、“\0”和“0”之間的區別。所以,為了解釋,為了避免重復之前說過的話:

A constant expression of type int with the value 0, or an expression of this type, cast to type void * is a null pointer constant, which if converted to a pointer becomes a null pointer. It is guaranteed by the standard to compare unequal to any pointer to any object or function.

類型int類型的常量表達式為0,或該類型的表達式,cast to類型void *是一個空指針常量,如果轉換為一個指針,它將變成一個空指針。它由標准來保證,比較不等於任何對象或函數的指針。

NULL is a macro, defined in as a null pointer constant.

NULL是一個宏,定義為空指針常量。

'\0' is a construction used to represent the null character, used to terminate a string.

“\0”是用來表示空字符的結構,用於終止字符串。

A null character is a byte which has all its bits set to 0.

null字符是一個字節,它的所有位都設置為0。

#3


15  

All three define the meaning of zero in different context.

這三個定義在不同的背景下定義了零的意義。

  • pointer context - NULL is used and means the value of the pointer is 0, independent of whether it is 32bit or 64bit (one case 4 bytes the other 8 bytes of zeroes).
  • 指針上下文- NULL被使用,意味着指針的值是0,獨立於它是32位還是64位(1個case 4字節,其他8字節的0)。
  • string context - the character representing the digit zero has a hex value of 0x30, whereas the NUL character has hex value of 0x00 (used for terminating strings).
  • 字符串上下文——表示數字零的字符具有0x30的十六進制值,而NUL字符的十六進制值為0x00(用於終止字符串)。

These three are always different when you look at the memory:

當你看記憶的時候,這三個總是不同的:

NULL - 0x00000000 or 0x00000000'00000000 (32 vs 64 bit)
NUL - 0x00 or 0x0000 (ascii vs 2byte unicode)
'0' - 0x20

I hope this clarifies it.

我希望這能澄清事實。

#4


5  

If NULL and 0 are equivalent as null pointer constants, which should I use? in the C FAQ list addresses this issue as well:

如果NULL和0等價為空指針常量,我應該使用哪個?在cfaq列表中也解決了這個問題:

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.

C程序員必須明白,在指針的上下文中,NULL和0是可以互換的,而uncast 0是完全可以接受的。任何使用NULL(相對於0)應該被看作是一個溫和的提示,提示有一個指針;程序員不應該依賴它(不是為了自己的理解,也不是為了編譯器)來區分指針0和整數0。

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

只有在指針上下文中,NULL和0是等價的。當需要其他類型的0時,不應該使用NULL,即使它可能起作用,因為這樣做會發送錯誤的樣式信息。(此外,ANSI允許將NULL定義為((void *)0),這在非指針上下文中完全不起作用。)特別是,當需要ASCII NULL字符時,不要使用NULL。提供自己的定義

#define NUL '\0'

if you must.

如果你必須。

#5


5  

What is the difference between NULL, ‘\0’ and 0

0和0之間的區別是什么?

"null character (NUL)" is easiest to rule out. '\0' is a character literal. In C, it is implemented as int, so, it's the same as 0, which is of INT_TYPE_SIZE. In C++, character literal is implemented as char, which is 1 byte. This is normally different from NULL or 0.

“空字符(NUL)”是最容易排除的。“\0”是一個字符文字。在C中,它被實現為int,因此,它與INT_TYPE_SIZE的0相同。在c++中,字符文字被實現為char,即1個字節。這通常不同於NULL或0。

Next, NULL is a pointer value that specifies that a variable does not point to any address space. Set aside the fact that it is usually implemented as zeros, it must be able to express the full address space of the architecture. Thus, on a 32-bit architecture NULL (likely) is 4-byte and on 64-bit architecture 8-byte. This is up to the implementation of C.

接下來,NULL是一個指針值,它指定變量不指向任何地址空間。拋開它通常被實現為零的事實,它必須能夠表達體系結構的完整地址空間。因此,在32位體系結構上,NULL(可能)是4字節和64位架構8字節。這取決於C的實現。

Finally, the literal 0 is of type int, which is of size INT_TYPE_SIZE. The default value of INT_TYPE_SIZE could be different depending on architecture.

最后,文字0是int類型,大小為INT_TYPE_SIZE。INT_TYPE_SIZE的默認值可能因架構不同而不同。

Apple wrote:

蘋果寫道:

The 64-bit data model used by Mac OS X is known as "LP64". This is the common data model used by other 64-bit UNIX systems from Sun and SGI as well as 64-bit Linux. The LP64 data model defines the primitive types as follows:

Mac OS X使用的64位數據模型被稱為“LP64”。這是Sun、SGI以及64位Linux的其他64位UNIX系統使用的通用數據模型。LP64數據模型定義了以下基本類型:

  • ints are 32-bit
  • 整數是32位
  • longs are 64-bit
  • 多頭是64位
  • long-longs are also 64-bit
  • long-longs也是64位
  • pointers are 64-bit
  • 指針是64位

Wikipedia 64-bit:

維基百科64位:

Microsoft's VC++ compiler uses the LLP64 model.

微軟的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       ?

Edit: Added more on the character literal.

編輯:添加更多的字符文字。

#include <stdio.h>

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

The above code returns 4 on gcc and 1 on g++.

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

#6


2  

A one-L NUL, it ends a string.

一個l NUL,它結束一個字符串。

A two-L NULL points to no thing.

一個2 - l的空值。

And I will bet a golden bull

我敢打賭一只金牛。

That there is no three-L NULLL.

沒有3 - l零。

How do you deal with NUL?

你如何處理NUL?

#7


2  

One good piece which helps me when starting with C(Taken from the Expert C Programming by Linden)

從C開始(從Linden的專家C編程開始)

The One 'l' nul and the Two 'l' null

一個'l' nul和兩個'l' null。

Memorize this little rhyme to recall the correct terminology for pointers and ASCII zero:

記住這個小韻文,回憶一下指針和ASCII 0的正確術語:

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. 

The ASCII character with the bit pattern of zero is termed a "NUL". The special pointer value that means the pointer points nowhere is "NULL". The two terms are not interchangeable in meaning.

帶有位模式為0的ASCII字符被稱為“NUL”。特殊的指針值,指的是指針指向的任何地方都是“NULL”。這兩項在意義上不能互換。

#8


1  

"NUL" is not 0, but refers to the ASCII NUL character. At least, that's how I've seen it used. The null pointer is often defined as 0, but this depends on the environment you are running in, and the specification of whatever operating system or language you are using.

“NUL”不是0,而是指ASCII字符。至少我是這么看的。空指針通常被定義為0,但這取決於您正在運行的環境,以及您正在使用的任何操作系統或語言的規范。

In ANSI C, the null pointer is specified as the integer value 0. So any world where that's not true is not ANSI C compliant.

在ANSI C中,空指針被指定為整數值0。所以任何不真實的世界都不是ANSI C兼容的。

#9


0  

A byte with a value of 0x00 is, on the ASCII table, the special character called "NUL" or "NULL". In C, since you shouldn't embed control characters in your source code, this is represented in C strings with an escaped 0, i.e., "\0".

一個值為0x00的字節是在ASCII表上,稱為“NUL”或“NULL”的特殊字符。在C語言中,由於您不應該在源代碼中嵌入控制字符,所以在C字符串中表示的是一個轉義為0的字符串,即。,“\ 0”。

But a true NULL is not a value. It is the absence of a value. For a pointer, it means the pointer has nothing to point to. In a database, it means there is no value in a field (which is not the same thing as saying the field is blank, 0, or filled with spaces).

但是一個真正的空值不是一個值。它是沒有價值的。對於一個指針,它意味着指針沒有指向。在數據庫中,它意味着字段中沒有值(這與說字段為空、0或填充空格是不一樣的)。

The actual value a given system or database file format uses to represent a NULL isn't necessarily 0x00.

給定系統或數據庫文件格式用來表示NULL的實際值不一定是0x00。

#10


-1  

NULL is not guaranteed to be 0 -- its exact value is architecture-dependent. Most major architectures define it to (void*)0.

NULL不能保證為0——它的確切值是與體系結構相關的。大多數主要的體系結構都將其定義為(void*)0。

'\0' will always equal 0, because that is how byte 0 is encoded in a character literal.

'\0'將始終等於0,因為這就是字節0編碼在字符文字中的方式。

I don't remember whether C compilers are required to use ASCII -- if not, '0' might not always equal 48. Regardless, it's unlikely you'll ever encounter a system which uses an alternative character set like EBCDIC unless you're working on very obscure systems.

我不記得是否需要C編譯器來使用ASCII——如果不是的話,“0”可能不總是等於48。無論如何,你不太可能遇到一個系統,它使用一個像EBCDIC這樣的替代字符集,除非你在一個非常模糊的系統上工作。

The sizes of the various types will differ on 64-bit systems, but the integer values will be the same.

不同類型的大小在64位系統上是不同的,但是整型值是相同的。


Some commenters have expressed doubt that NULL be equal to 0, but not be zero. Here is an example program, along with expected output on such a system:

一些評論者表示懷疑零等於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;
}

That program could print:

這個項目可以打印:

NULL == 0
NULL = 0x00000001

#11


-2  

(void*) 0 is NULL, and '\0' represents the end of a string.

(void*) 0為空,“\0”表示字符串的結束。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/08/18/eff88b9d58711e1b472d72133411d22c.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com