2010-10-24 33 views
33

Tôi là một người mới hoàn thành cho C, và trong công việc đại học của tôi tôi đã đi qua ý kiến ​​trong mã mà thường đề cập đến de-tham chiếu một con trỏ NULL. Tôi có một nền tảng trong C#, tôi đã nhận được rằng điều này có thể tương tự như một "NullReferenceException" mà bạn nhận được trong. Net, nhưng bây giờ tôi đang có nghi ngờ nghiêm trọng.Chính xác những gì có nghĩa là "de-tham chiếu một con trỏ NULL"?

Ai đó có thể vui lòng giải thích cho tôi về các thuật ngữ laymans chính xác điều này là gì và tại sao nó xấu?

+0

Hãy nhớ rằng làm như vậy dẫn đến hành vi không xác định. Bạn không nhận được ngoại lệ hoặc bất cứ điều gì, trong C hoặc C++. – GManNickG

+0

Bạn có thể muốn đặt xuống một số mã ví dụ. Dường như mọi người (kể cả tôi) không hiểu những gì bạn đang cố hỏi. –

+0

Không cần mã (không có bất kỳ) - Đây là một vấn đề khái niệm tôi đang gặp phải, cố gắng để có được đầu của tôi xung quanh thuật ngữ "dereferencing" và tại sao tôi nên quan tâm đến nó. – Ash

Trả lời

47

Một NULL điểm con trỏ tới bộ nhớ mà không tồn tại. Đây có thể là địa chỉ 0x00000000 hoặc bất kỳ giá trị được xác định nào khác (miễn là nó không bao giờ có thể là địa chỉ thực). Dereferencing nó có nghĩa là cố gắng truy cập vào bất cứ điều gì được trỏ đến bởi con trỏ. Nhà điều hành * là các nhà điều hành dereferencing:

int a, b, c; // some integers 
int *pi;  // a pointer to an integer 

a = 5; 
pi = &a; // pi points to a 
b = *pi; // b is now 5 
pi = NULL; 
c = *pi; // this is a NULL pointer dereference 

Đây chính là điều tương tự như một NullReferenceException trong C#, ngoại trừ việc con trỏ trong C có thể trỏ đến bất kỳ đối tượng dữ liệu, thậm chí yếu tố bên trong một mảng.

+8

@Ash: Một con trỏ chứa một địa chỉ bộ nhớ * tham chiếu * đến một cái gì đó. Để truy cập thứ gì đó * được tham chiếu * bằng địa chỉ bộ nhớ đó, bạn phải * de-reference * địa chỉ bộ nhớ. –

+0

@Ash, mà trong silico cho biết, nhưng khi bạn không tham khảo bạn nhận được giá trị được lưu trữ tại địa chỉ bộ nhớ. Hãy thử một lần. Do int p; printf ("% p \ n", &p); nó sẽ in ra một địa chỉ. Khi bạn không tạo một con trỏ (* var), để lấy địa chỉ bạn sử dụng & var – Matt

+0

@Greg Làm thế nào về khi bạn làm 'char * foo = NULL' và sau đó sử dụng & foo? – Bionix1441

-1

Từ wiki

Một con trỏ null có giá trị dành riêng, thường xuyên nhưng không nhất thiết phải là giá trị zero, chỉ ra rằng nó đề cập đến không có đối tượng
..

Từ một con trỏ null giá trị không không đề cập đến một đối tượng có ý nghĩa, một nỗ lực để dereference một con trỏ null thường gây ra một lỗi thời gian chạy.

int val =1; 
int *p = NULL; 
*p = val; // Whooosh!!!! 
+0

Cảm ơn câu trả lời của bạn, tôi ổn với con trỏ NULL là gì, tôi không chắc chắn về cách "dereferencing" phù hợp với lược đồ của sự vật . – Ash

2

Nó có nghĩa

myclass *p = NULL; 
*p = ...; // illegal: dereferencing NULL pointer 
... = *p; // illegal: dereferencing NULL pointer 
p->meth(); // illegal: equivalent to (*p).meth(), which is dereferencing NULL pointer 

myclass *p = /* some legal, non-NULL pointer */; 
*p = ...; // Ok 
... = *p; // Ok 
p->meth(); // Ok, if myclass::meth() exists 

về cơ bản, hầu hết mọi thứ liên quan đến (*p) hoặc ngầm liên quan đến (*p), ví dụ p->... là viết tắt của (*p). ...; ngoại trừ khai báo con trỏ.

+0

Ông đã gắn thẻ câu hỏi của mình là C không C++ – GWW

+2

@GWW: nó có chính xác cùng ngữ nghĩa trong C và trong C++, ngoại trừ có lẽ C không có lớp costum –

+0

Không phải là 'p-> meth()' chỉ là viết tắt của '(* p) .meth()', với sau này có sẵn trong cả C và C++? – Arun

0

Trích dẫn từ wikipedia:

Một con trỏ tham chiếu đến một vị trí trong bộ nhớ , và lấy giá trị tại vị trí một con trỏ dùng để chỉ được biết đến như dereferencing con trỏ.

Dereferencing được thực hiện bằng cách áp dụng toán tử unary * trên con trỏ.

int x = 5; 
int * p;  // pointer declaration 
p = &x;  // pointer assignment 
*p = 7;  // pointer dereferencing, example 1 
int y = *p; // pointer dereferencing, example 2 

"dereferencing một con trỏ NULL" có nghĩa là thực hiện *p khi pNULL

20

dereferencing chỉ có nghĩa là đọc giá trị bộ nhớ tại một địa chỉ nhất định. Vì vậy, khi bạn có một con trỏ đến một cái gì đó, để dereference con trỏ có nghĩa là để đọc hoặc ghi dữ liệu mà con trỏ trỏ đến.

Trong C, toán tử unsemble * là toán tử dereferencing.Nếu x là một con trỏ, thì *x là những gì x trỏ đến. Nhà điều hành độc lập & là địa chỉ -of nhà điều hành. Nếu x là bất cứ điều gì, thì &x là địa chỉ mà tại đó x được lưu trữ trong bộ nhớ. Các *& nhà khai thác là ngược nhau: nếu x là bất kỳ dữ liệu, và y là bất kỳ con trỏ, sau đó những phương trình luôn đúng:

*(&x) == x 
&(*y) == y 

Một con trỏ null là một con trỏ không trỏ đến bất kỳ hợp lệ dữ liệu (nhưng nó không phải là con trỏ duy nhất). Tiêu chuẩn C nói rằng đó là hành vi không xác định để dereference một con trỏ null. Điều này có nghĩa rằng hoàn toàn bất cứ điều gì có thể xảy ra: chương trình có thể sụp đổ, nó có thể tiếp tục làm việc âm thầm, hoặc nó có thể xóa ổ cứng của bạn (mặc dù đó là khá khó xảy ra).

Trong hầu hết các triển khai, bạn sẽ nhận được "lỗi phân đoạn" hoặc "vi phạm truy cập" nếu bạn cố gắng làm như vậy, điều này hầu như luôn dẫn đến chương trình của bạn bị hệ điều hành chấm dứt. Dưới đây là một cách để một con trỏ null có thể được dereferenced:

int *x = NULL; // x is a null pointer 
int y = *x;  // CRASH: dereference x, trying to read it 
*x = 0;   // CRASH: dereference x, trying to write it 

Và vâng, dereferencing một con trỏ null là khá nhiều giống hệt như một NullReferenceException trong C# (hoặc một NullPointerException trong Java), ngoại trừ các tiêu chuẩn langauge là nhiều hơn một chút hữu ích ở đây. Trong C#, dereferencing một tham chiếu null có hành vi được xác định rõ: nó luôn ném một NullReferenceException. Không có cách nào mà chương trình của bạn có thể tiếp tục làm việc âm thầm hoặc xóa ổ đĩa cứng của bạn như trong C (trừ khi có lỗi trong thời gian chạy ngôn ngữ, nhưng một lần nữa điều đó cũng không khả thi).

Các vấn đề liên quan