Helpex - Trao đổi & giúp đỡ Đăng nhập
269

Trong C, có vẻ như là sự khác biệt giữa các giá trị khác nhau của zero - NULL, NUL0.

Tôi biết rằng các ký tự ASCII '0'để đánh giá 48hay 0x30.

Con NULLtrỏ thường được định nghĩa là:

#define NULL 0

Hoặc là

#define NULL (void *)0

Ngoài ra, có những NULnhân vật '\0'dường 0như cũng đánh giá là tốt.

Có những lúc ba giá trị này không thể bằng nhau?

Điều này cũng đúng trên hệ thống 64 bit?

269 hữu ích 2 bình luận 301k xem chia sẻ
11 trả lời 11
319

Lưu ý: Câu trả lời này áp dụng cho ngôn ngữ C, không phải C ++.


Con trỏ Null

Hằng số nguyên 0có nghĩa khác nhau tùy thuộc vào ngữ cảnh mà nó được sử dụng. Trong mọi trường hợp, nó vẫn là một hằng số nguyên với giá trị 0, nó chỉ được mô tả theo các cách khác nhau.

Nếu một con trỏ đang được so sánh với chữ không đổi 0, thì đây là kiểm tra xem con trỏ có phải là con trỏ không. Điều này 0sau đó được gọi là một hằng con trỏ null. Tiêu chuẩn C định nghĩa rằng 0truyền tới loại void *vừa là con trỏ null và hằng số con trỏ null.

Ngoài ra, để giúp dễ đọc, macro NULLđược cung cấp trong tệp tiêu đề stddef.h. Tùy thuộc vào trình biên dịch của bạn, nó có thể có thể #undef NULLvà xác định lại nó thành một cái gì đó lập dị.

Do đó, đây là một số cách hợp lệ để kiểm tra con trỏ null:

if (pointer == NULL)

NULLđược định nghĩa để so sánh bằng với một con trỏ null. Đó là việc thực hiện được định nghĩa định nghĩa thực sự NULLlà gì, miễn là nó là một con trỏ null hợp lệ.

if (pointer == 0)

0 là một đại diện khác của hằng số con trỏ null.

if (!pointer)

ifTuyên bố này hoàn toàn kiểm tra "không phải là 0", vì vậy chúng tôi đảo ngược điều đó thành "0".

Sau đây là các cách INVALID để kiểm tra con trỏ null:

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

Đối với trình biên dịch, đây không phải là kiểm tra con trỏ null, mà là kiểm tra đẳng thức trên hai biến. Điều này có thể hoạt động nếu mynull không bao giờ thay đổi mã và tối ưu hóa trình biên dịch liên tục gập 0 thành câu lệnh if, nhưng điều này không được đảm bảo và trình biên dịch phải tạo ra ít nhất một thông báo chẩn đoán (cảnh báo hoặc lỗi) theo Tiêu chuẩn C.

Lưu ý rằng con trỏ null trong ngôn ngữ C là gì. Nó không quan trọng trên kiến ​​trúc cơ bản. Nếu kiến ​​trúc cơ bản có giá trị con trỏ null được xác định là địa chỉ 0xDEADBEEF, thì tùy thuộc vào trình biên dịch để sắp xếp mớ hỗn độn này.

Như vậy, ngay cả trên kiến ​​trúc ngộ nghĩnh này, các cách sau đây vẫn là những cách hợp lệ để kiểm tra con trỏ null:

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

Sau đây là các cách INVALID để kiểm tra con trỏ null:

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

vì những thứ này được xem bởi một trình biên dịch như là so sánh bình thường.

Nhân vật Null

'\0'được định nghĩa là một ký tự null - đó là một ký tự có tất cả các bit được đặt thành 0. Điều này không có gì để làm với con trỏ. Tuy nhiên, bạn có thể thấy một cái gì đó tương tự như mã này:

if (!*string_pointer)

kiểm tra nếu con trỏ chuỗi đang trỏ vào một ký tự null

if (*string_pointer)

kiểm tra nếu con trỏ chuỗi đang trỏ vào một ký tự không null

Đừng nhầm lẫn với con trỏ null. Chỉ vì cách biểu diễn bit là như nhau và điều này cho phép một số trường hợp giao nhau thuận tiện, chúng không thực sự giống nhau.

Ngoài ra, '\0'là (như tất cả các ký tự chữ) là một hằng số nguyên, trong trường hợp này có giá trị bằng không. Vì vậy, '\0'hoàn toàn tương đương với một 0hằng số nguyên không được cung cấp - sự khác biệt duy nhất là ở mục đích mà nó truyền tải tới người đọc con người ("Tôi đang sử dụng điều này như một ký tự null.").

Tài liệu tham khảo

Xem Câu hỏi 5.3 của Câu hỏi thường gặp về comp.lang.c để biết thêm. Xem pdf này cho tiêu chuẩn C. Kiểm tra các phần 6.3.2.3 Con trỏ, đoạn 3.

319 hữu ích 5 bình luận chia sẻ
30

Dường như một số người hiểu sai về sự khác biệt giữa NULL, '\ 0' và 0 là gì. Vì vậy, để giải thích và trong nỗ lực tránh lặp lại những điều đã nói trước đó:

Một biểu thức hằng của kiểu int có giá trị 0 hoặc biểu thức của kiểu này, được chuyển thành kiểu void * là hằng số con trỏ null , nếu được chuyển đổi thành con trỏ sẽ trở thành con trỏ null . Nó được đảm bảo bởi tiêu chuẩn để so sánh không bằng nhau với bất kỳ con trỏ nào với bất kỳ đối tượng hoặc chức năng nào .

NULL là một macro, được định nghĩa là hằng số con trỏ null .

'\ 0' là cấu trúc được sử dụng để thể hiện ký tự null , được sử dụng để chấm dứt chuỗi.

Một ký tự null là một byte có tất cả các bit của nó được đặt thành 0.

30 hữu ích 2 bình luận chia sẻ
14

Tất cả ba xác định ý nghĩa của số không trong bối cảnh khác nhau.

  • bối cảnh con trỏ - NULL được sử dụng và có nghĩa là giá trị của con trỏ là 0, không phụ thuộc vào việc nó là 32 bit hay 64 bit (một trường hợp 4 byte cho 8 byte khác của số 0).
  • bối cảnh chuỗi - ký tự đại diện cho chữ số 0 có giá trị hex là 0x30, trong khi ký tự NUL có giá trị hex là 0x00 (được sử dụng để kết thúc chuỗi).

Ba cái này luôn khác nhau khi bạn nhìn vào bộ nhớ:

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

Tôi hy vọng điều này làm rõ nó.

14 hữu ích 5 bình luận chia sẻ
6

Nếu NULL và 0 tương đương với hằng số con trỏ null, tôi nên sử dụng cái nào? trong danh sách C FAQ cũng đề cập đến vấn đề này:

Các lập trình viên C phải hiểu điều đó NULL0có thể hoán đổi cho nhau trong bối cảnh con trỏ, và việc uncast 0 là hoàn toàn chấp nhận được. Bất kỳ việc sử dụng NULL (trái ngược với 0) nên được coi là một lời nhắc nhở nhẹ nhàng rằng một con trỏ có liên quan; lập trình viên không nên phụ thuộc vào nó (vì sự hiểu biết của chính họ hoặc của người biên dịch) để phân biệt con trỏ 0với số nguyên 0.

Nó chỉ trong bối cảnh con trỏ NULL0tương đương. NULLkhông nên được sử dụng khi một loại khác 0được yêu cầu, mặc dù nó có thể hoạt động, bởi vì làm như vậy sẽ gửi thông điệp phong cách sai. (Hơn nữa, ANSI cho phép định nghĩa về NULLđược ((void *)0), mà sẽ không làm việc ở tất cả trong bối cảnh không con trỏ.) Đặc biệt, không sử dụng NULLkhi các ký tự null ASCII ( NUL) là mong muốn. Cung cấp định nghĩa của riêng bạn

#define NUL '\0'

nếu bạn phải.

6 hữu ích 0 bình luận chia sẻ
5

Sự khác biệt giữa NULL, '\ 0' và 0 là gì

"null character (NUL)" là dễ loại trừ nhất. '\0'là một nhân vật theo nghĩa đen. Trong C, nó được triển khai như là int, vì vậy, nó giống như 0, là của INT_TYPE_SIZE. Trong C ++, ký tự bằng chữ được triển khai dưới dạng char1 byte. Điều này thường khác với NULLhoặc 0.

Tiếp theo, NULLlà một giá trị con trỏ chỉ định rằng một biến không trỏ đến bất kỳ không gian địa chỉ nào. Đặt sang một bên thực tế là nó thường được thực hiện dưới dạng số không, nó phải có khả năng thể hiện không gian địa chỉ đầy đủ của kiến ​​trúc. Do đó, trên kiến ​​trúc 32 bit, NULL (có khả năng) là 4 byte và trên kiến ​​trúc 64 bit 8 byte. Điều này phụ thuộc vào việc thực hiện C.

Cuối cùng, nghĩa đen 0là loại int, có kích thước INT_TYPE_SIZE. Giá trị mặc định INT_TYPE_SIZEcó thể khác nhau tùy theo kiến ​​trúc.

Apple đã viết:

Mô hình dữ liệu 64 bit được sử dụng bởi Mac OS X được gọi là "LP64". Đây là mô hình dữ liệu phổ biến được sử dụng bởi các hệ thống UNIX 64 bit khác từ Sun và SGI cũng như Linux 64 bit. Mô hình dữ liệu LP64 định nghĩa các kiểu nguyên thủy như sau:

  • số nguyên là 32 bit
  • dài là 64-bit
  • dài cũng là 64-bit
  • con trỏ là 64 bit

Wikipedia 64-bit :

Trình biên dịch VC ++ của Microsoft sử dụng mô hình 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       ?

Chỉnh sửa : Thêm nhiều hơn vào các ký tự chữ.

#include <stdio.h>

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

Đoạn mã trên trả về 4 trên gcc và 1 trên g ++.

5 hữu ích 3 bình luận chia sẻ
4

Một NUL một L, nó kết thúc một chuỗi.

Một NULL hai L chỉ vào không có điều gì.

Và tôi sẽ đặt cược một con bò vàng

Rằng không có NULLL ba L.

Làm thế nào để bạn đối phó với NUL?

4 hữu ích 0 bình luận chia sẻ
3

Một phần tốt giúp tôi khi bắt đầu với C (Lấy từ chương trình Expert C của Linden)

Một 'l' nul và Hai 'l' null

Ghi nhớ vần nhỏ này để nhớ lại thuật ngữ chính xác cho con trỏ và ASCII zero:

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. 

Ký tự ASCII có mẫu bit bằng 0 được gọi là "NUL". Giá trị con trỏ đặc biệt có nghĩa là điểm con trỏ không ở đâu là "NULL". Hai thuật ngữ không thể thay thế cho nhau.

3 hữu ích 1 bình luận chia sẻ
2

"NUL" không phải là 0, nhưng đề cập đến ký tự ASCII NUL. Ít nhất, đó là cách tôi đã thấy nó được sử dụng. Con trỏ null thường được định nghĩa là 0, nhưng điều này phụ thuộc vào môi trường bạn đang chạy và đặc điểm kỹ thuật của bất kỳ hệ điều hành hoặc ngôn ngữ nào bạn đang sử dụng.

Trong ANSI C, con trỏ null được chỉ định là giá trị nguyên 0. Vì vậy, bất kỳ thế giới nào không đúng đều không tuân thủ ANSI C.

2 hữu ích 0 bình luận chia sẻ
0

Một byte có giá trị 0x00 là, trên bảng ASCII, ký tự đặc biệt gọi là "NUL" hoặc "NULL". Trong C, vì bạn không nên nhúng các ký tự điều khiển trong mã nguồn của mình, nên ký tự này được thể hiện bằng các chuỗi C có 0 thoát, nghĩa là "\ 0".

Nhưng một NULL thực sự không phải là một giá trị. Đó là sự vắng mặt của một giá trị. Đối với một con trỏ, nó có nghĩa là con trỏ không có gì để trỏ đến. Trong cơ sở dữ liệu, điều đó có nghĩa là không có giá trị trong một trường (điều này không giống với việc nói trường đó trống, 0 hoặc chứa đầy khoảng trắng).

Các thực tế giá trị của một hệ thống nhất định hoặc định dạng tập tin cơ sở dữ liệu sử dụng để đại diện cho một NULL không nhất thiết phải là 0x00.

0 hữu ích 0 bình luận chia sẻ
1

NULLkhông được đảm bảo là 0 - giá trị chính xác của nó phụ thuộc vào kiến ​​trúc. Hầu hết các kiến ​​trúc chính định nghĩa nó (void*)0.

'\0' sẽ luôn bằng 0, vì đó là cách byte 0 được mã hóa theo một ký tự.

Tôi không nhớ liệu trình biên dịch C được yêu cầu phải sử dụng ASCII - nếu không, '0'có thể không luôn luôn bằng 48. Bất kể, chắc bao giờ bạn sẽ gặp phải một hệ thống trong đó sử dụng một nhân vật thay thế thiết như EBCDIC trừ khi bạn đang làm việc trên rất hệ thống tối nghĩa.

Kích thước của các loại khác nhau sẽ khác nhau trên các hệ thống 64 bit, nhưng các giá trị nguyên sẽ giống nhau.


Một số bình luận đã bày tỏ nghi ngờ rằng NULL bằng 0, nhưng không phải bằng không. Đây là một chương trình ví dụ, cùng với đầu ra dự kiến ​​trên một hệ thống như vậy:

#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;
}

Chương trình đó có thể in:

NULL == 0
NULL = 0x00000001
1 hữu ích 5 bình luận chia sẻ
2

(void *) 0 là NULL và '\ 0' đại diện cho phần cuối của chuỗi.

2 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c pointers null , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading