Trợ giúp:Chỗ thử

Bách khoa toàn thư mở Wikipedia
Bước tới: menu, tìm kiếm

Trong ngành điện toán, khái niệm con trỏ rỗng chỉ một biến con trỏ có một giá trị định sẵn khiến cho nó không trỏ được tới bất kỳ một đối tượng chính tắc nào. Các ngôn ngữ lập trình thường sử dụng con trỏ rỗng trong trường hợp cuối một list không rõ độ dài hoặc một tác vụ nào đó thất bại; cách sử dụng con trỏ rỗng tuơng đương với các kiểu rỗng và ứng với giá trị Nothing trong kiểu lựa chọn.

Không nên nhầm lẫn con trỏ rỗng với một biến con trỏ chưa được khởi tạo giá trị cho nó: mục đích của việc sử dụng con trỏ rỗng là để để bảo đảm phép so sánh không bằng với bất kỳ con trỏ nào trỏ tới một đối tượng chính tắc. Tuy nhiên, tùy vào từng ngôn ngữ và phương pháp lập trình của nó, một biến con trỏ chưa được khởi tạo không chắc chắn sẽ thực hiện được yêu cầu trên. Khi thực hiện phép so sánh, nó có thể cho ra kết quả bằng với một giá trị nào đó, là một con trỏ chính tắc; hoặc có thể bằng với một con trỏ rỗng khác. Và như thế, biến con trỏ này có thể đóng cả hai vai trò ở những thời điểm khác nhau.

Về mặt ngữ nghĩa, con trỏ rỗng (null pointer) khác với giá trị rỗng (null value). Con trỏ rỗng trong hầu hết ngôn ngữ lập trình có nghĩa là "không có giá trị", trong khi giá trị rỗng trong một cơ sở dữ liệu quan hệ có nghĩa là "có giá trị không rõ". Điều này tạo ra một khác biệt trong thực tế: hầu hết ngôn ngữ lập trình xem hai con trỏ rỗng bằng nhau, nhưng các hệ cơ sở dữ liệu quan hệ lại không coi hai giá trị rỗng là bằng nhau(vì chúng biểu diễn các giá trị không rõ, và như thế, không thể khẳng định chúng có bằng nhau không).

C[sửa | sửa mã nguồn]

Trong C, hai con trỏ rỗng của bất kỳ kiểu nào cũng được đảm bảo là bằng nhau.[1] Macro NULL được dùng để định nghĩa một hằng số con trỏ rỗng,[2] mà trong C99 can be portably expressed as the integer value 0 converted implicitly or explicitly to the type void*.[3]

Dereferencing the NULL pointer typically results in an attempted read or write from memory that is not mapped - triggering a segmentation fault or access violation. This may represent itself to the developer as a program crash, or be transformed into an exception that can be caught. There are, however, certain circumstances where this is not the case. For example, in x86-real mode, the address 0000:0000 is readable and usually writable, hence dereferencing the null pointer is a perfectly valid but typically unwanted action that may lead to undefined but non-crashing behaviour in the application. Note also that there are occasions when dereferencing the NULL is intentional and well defined; for example BIOS code written in C for 16-bit real-mode x86 devices may write the IDT at physical address 0 of the machine by dereferencing a NULL pointer for writing. It is also possible for the compiler to optimize away the `NULL` pointer dereference, avoiding a segmentation fault but causing other undesired behavior.

C++[sửa | sửa mã nguồn]

In C++, while the NULL macro was inherited from C, the integer literal for zero has been traditionally preferred to represent a null pointer constant.[4] However, C++11 has introduced an explicit nullptr constant to be used instead.

Ngôn ngữ khác[sửa | sửa mã nguồn]

In some programming language environments (at least one proprietary Lisp implementation, for example),[cần dẫn nguồn] the value used as the null pointer (called nil in Lisp) may actually be a pointer to a block of internal data useful to the implementation (but not explicitly reachable from user programs), thus allowing the same register to be used as a useful constant and a quick way of accessing implementation internals. This is known as the nil vector.

In languages with a tagged architecture, a possibly null pointer can be replaced with a tagged union which enforces explicit handling of the exceptional case; in fact, a possibly null pointer can be seen as a tagged pointer with a computed tag.

Dereferencing[sửa | sửa mã nguồn]

Because a null pointer does not point to a meaningful object, an attempt to dereference (ie. access the data stored at that memory location) a null pointer usually (but not always) causes a run-time error or immediate program crash.

  • In C, the behavior of dereferencing a null pointer is undefined.[5] Many implementations cause such code to result in the program being halted with a segmentation fault, because the null pointer representation is chosen to be an address that is never allocated by the system for storing objects. However, this behavior is not universal.
  • In Java, access to a null reference triggers a Bản mẫu:Javadoc:SE (NPE), which can be caught by error handling code, but the preferred practice is to ensure that such exceptions never occur.
  • In .NET, access to null reference triggers a NullReferenceException to be thrown. Although catching these is generally considered bad practice, this exception type can be caught and handled by the program.
  • In Objective-C, messages may be sent to a nil object (which is a null pointer) without causing the program to be interrupted; the message is simply ignored, and the return value (if any) is nil or 0, depending on the type.[6]

Lược sử[sửa | sửa mã nguồn]

In 2009 C.A.R. Hoare stated[7][8] that he invented the null reference in 1965 as part of the Algol W language, although NIL had existed in Lisp since 1959[cần dẫn nguồn]. In that 2009 reference Hoare describes his invention as a "billion-dollar mistake":

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

Tham khảo[sửa | sửa mã nguồn]

  1. ^ ISO/IEC 9899, clause, paragraph 4.
  2. ^ ISO/IEC 9899, clause 7.17, paragraph 3: NULL... which expands to an implementation-defined null pointer constant...
  3. ^ ISO/IEC 9899, clause, paragraph 3.
  4. ^ Stroustrup, Bjarne (tháng 3 năm 2001). “Chapter 5: Pointers, Arrays, and Structures: 5.1.1: Zero”. The C++ Programming Language (ấn bản 14). United States and Canada: Addison–Wesley. tr. 88. ISBN 0-201-88954-4. In C, it has been popular to define a macro NULL to represent the zero pointer. Because of C++'s tighter type checking, the use of plain 0, rather than any suggested NULL macro, leads to fewer problems. If you feel you must define NULL. use
        const int NULL = 0;
    The const qualifier (§5.4) prevents accidental redefinition of NULL and ensures that NULL can be used where a constant is required.
  5. ^ ISO/IEC 9899, clause, paragraph 4.
  6. ^ The Objective-C 2.0 Programming Language, section "Sending Messages to nil".
  7. ^ Tony Hoare (2009). “Null References: The Billion Dollar Mistake”. QCon London. 
  8. ^ Tony Hoare (25 tháng 8 năm 2009). “Null References: The Billion Dollar Mistake”. 

Liên kết ngoài[sửa | sửa mã nguồn]