2010-02-04 17 views
22

Tôi biết rằng chúng tôi có các con trỏ khác nhau như int, floatchar. Con trỏ void là con trỏ duy nhất có thể chứa tất cả các con trỏ khác.Tại sao chúng tôi có các con trỏ khác ngoài void

Các con trỏ khác chỉ tồn tại cho sự linh hoạt để làm số học con trỏ?

Có lý do nào khác mà con trỏ khác với void có mặt bằng ngôn ngữ C không?

+1

tôi có thể biết lý do cho phiếu giảm giá không? – Vijay

+3

không có ý tưởng, nhưng tôi sẽ nguy hiểm đoán: ai đó nghĩ rằng bạn không biết đủ về những gì bạn đã yêu cầu để thực sự hiểu một câu trả lời? – Will

+0

Đừng quên trỏ đến cấu trúc. – phkahler

Trả lời

20

Nhập an toàn. Xác định loại con trỏ giúp trình biên dịch tìm lỗi mà bạn đang cố gắng sử dụng dữ liệu của loại sai thông qua một con trỏ. Đó là lý do C có loại ở nơi đầu tiên.

+3

-1, rất gây hiểu lầm: sự tồn tại của các loại không ngụ ý sự tồn tại của an toàn loại. Đó là chủ yếu là một thực tế là loại đúc con trỏ ref/dereferencing là như vậy hoàn toàn không bị giới hạn rằng C là một loại ngôn ngữ không an toàn. Thay vào đó, điểm là các kiểu mô tả ngữ nghĩa của con trỏ ref/dereferencing. –

3

Khi bạn sử dụng con trỏ để phao hoặc trình biên dịch int (ví dụ) biết số bytes cần lấy từ bộ nhớ (sizeof (int) cho int * chẳng hạn).

Với khoảng trống Bạn sẽ phải nói với từng thời gian để biên dịch bao nhiêu byte nó phải thực hiện (bằng cách viết (int *) some_void_ptr ví dụ

Nhưng đây là đơn giản hóa lớn

0

Hai Words..: gõ An toàn

có một ít miếng ngon trên type safety (or lack thereof) in C trên Wikipedia mà có thể làm sáng tỏ cho bạn.

+0

-1: cf. bình luận của tôi về câu trả lời của Max. –

8
int o = 12; 
void *i = &o; 

thế nào bạn sẽ truy cập vào int đó i điểm nếu chỉ có con trỏ void và không có int *. Bạn có thể biết rằng trên nền tảng của bạn một int là 4 byte, do đó bạn có thể memcpy 4 byte từ đầu của bất kỳ void * điểm vào một int tạm thời và sau đó sử dụng đó. Nhưng đó không phải là rất thuận tiện.

Hoặc cho một

struct Pair { 
    char *first; 
    char *second; 
}; 

cách hữu ích sẽ một khoảng trống con trỏ đến struct Pair được? Bạn có thể muốn truy cập vào thành viên first của mình và đó là rất nhiều công việc nếu bạn không thể có một con trỏ đến một cặp struct.

+0

+1 để trả lời câu hỏi mà không đưa ra xác nhận sai. –

0

Khi bạn lặp qua khối bộ nhớ được trỏ tới bởi một con trỏ, cần phải biết kích thước của kiểu dữ liệu mà bộ nhớ chứa. Giả sử bạn có hai con trỏ, một ký tự char charptr và int intptr, cả hai trỏ vào bộ nhớ tại byte X. charptr + 1 sẽ trỏ đến byte X + 1, trong khi intptr + 1 sẽ trỏ đến byte X + 4.

Một mảnh nhanh chóng và dơ bẩn mã nặng bằng văn bản để minh họa rằng:

#include <stdio.h> 

int main() 
{ 
    char * cptr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    short * sptr = (short*)cptr; 
    int * iptr = (int*)cptr; 
    long long * lptr = (long long*)cptr; 

    printf ("CHAR: %d, +1: %d\n",cptr,cptr+1); 
    printf ("SHORT: %d, +1: %d\n",sptr,sptr+1); 
    printf ("INT: %d, +1: %d\n",iptr,iptr+1); 
    printf ("LONG LONG: %d, +1: %d\n",lptr,lptr+1); 
} 

này nên:

  • tạo ra cảnh báo về việc đúc con trỏ của các kích cỡ khác nhau (loại an toàn),
  • đầu ra các số giống nhau trong cột đầu tiên (tất cả các con trỏ trỏ đến cùng một địa chỉ trong bộ nhớ), nhưng các số khác nhau trong cột thứ 2 (là địa chỉ cơ sở + kích thước của loại con trỏ: 1, 2, 4 và 8 byte).
13

Trình biên dịch cần phải biết các loại được chỉ định ở tất cả các loại mã sẽ không hoạt động.Hãy xem xét những điều sau:

 
*a = *b + *c; // Should this add char? int? float? 
s_ptr->x = 0; // How does the compiler know anything about the structure s_ptr points to? 
a[5] = 0;  // How far is a[5] from a[0]? 

Không có loại cho con trỏ sẽ không có loại cho bất kỳ thứ gì. Trình biên dịch sẽ bị mất hoàn toàn. Tóm lại, C và C++ được đánh máy mạnh mẽ và điều này chuyển sang con trỏ vì những lý do khá rõ ràng.

+0

Err, "mạnh mẽ" gõ có nghĩa là ngôn ngữ không thể làm typecasting incoherent. WP: "Không cho phép bất kỳ loại chuyển đổi nào. Giá trị của một loại không thể chuyển đổi thành loại khác, rõ ràng hoặc ngầm." http://en.wikipedia.org/wiki/Strongly_typed_programming_language –

+2

Tôi đang sử dụng định nghĩa yếu hơn như được giải thích thêm ở dưới trên trang wikipedia mà bạn liên kết :-) Mặc dù xấu của tôi. – phkahler

2

Thực ra, đó là "con trỏ để làm mất hiệu lực" cần được giải thích.

Trong ngôn ngữ lập trình nói chung và trong C nói riêng, chúng tôi thích các loại. Các loại là mạng lưới an toàn cơ bản để kiểm tra xem chúng ta có đang làm điều gì đó ngu xuẩn không, nơi "ngu xuẩn" có nghĩa là "giải thích một loạt các bit cho một cái gì đó mà chúng không phải là". Có thể lập trình không có loại, một số ngôn ngữ hoàn toàn không có bất kỳ loại nào (ví dụ như assembly hoặc Forth), nhưng điều này không dành cho những người yếu tim và nói chung, năng suất lập trình dường như được tăng cường rất nhiều bằng cách sử dụng các loại .

Vì vậy, khi chúng tôi có một con trỏ, chúng tôi muốn máy tính biết những gì nó có thể tìm thấy ở cuối con trỏ. Chúng tôi muốn một "con trỏ đến int" để máy tính kiểm tra khi chúng ta nhìn vào các bit ở cuối con trỏ, chúng ta xem chúng như là một "int" và không phải là cái gì khác.

"Con trỏ để làm trống" là con trỏ loại ít hơn, mà chúng tôi sử dụng khi hệ thống kiểu C không chụp được những gì chúng tôi đang thực hiện. Đó là một triệu chứng của C không thể làm theo sự phức tạp của mã chúng tôi đang sản xuất (hoặc có thể lập trình viên không đủ tốt để thể hiện những gì anh ta làm trong các ràng buộc của hệ thống kiểu C). Do đó, trong khi "void *" thuận tiện trong một số trường hợp, người ta nên xem nó như là ngoại lệ, và cố gắng tránh nó.

+1

Con trỏ để void tồn tại vì không có loại đối tượng cơ sở. –

+1

@Steven, không có nó không C không có đối tượng, đôi khi một blob chỉ đơn giản là không có loại, không phải là một loại cơ sở, không phải là một đối tượng/struct/bất cứ điều gì-bạn-muốn-to-gọi-nó loại, không phải bất kỳ kiểu. Việc sử dụng loại con trỏ đến không xác định chỉ là một trong những cách sử dụng nó. – wich

+0

@wich: Các ngôn ngữ như C# có loại cơ sở 'đối tượng', tất cả các phiên bản có thể được đưa lên (cho dù là Int32 hoặc Employee). Vì vậy, một tham chiếu C# 'object' phục vụ cùng chức năng như một con trỏ C++' void': nó có thể ám chỉ đến bất cứ thứ gì. –

0

Có bất kỳ lý do nào khác mà con trỏ khác với khoảng trống có trong ngôn ngữ C không?

Đó là một cách tuyệt vời để xử lý các khối bộ nhớ một cách tự do. :)

+0

Loại liên minh tốt hơn. –

+0

Vâng, tôi đồng ý! :) – SDReyes

2

Loại con trỏ trong C cho trình biên dịch biết kích thước của khối bộ nhớ sẽ được đọc trong trường hợp bạn cố gắng dereference nó. Nói cách khác, khi dereferencing một con trỏ int trình biên dịch biết rằng 4 byte phải được đọc sau khi địa chỉ. Đó là lý do tại sao dereferencing một con trỏ void mà không cần đưa nó vào một con trỏ đã nhập bị cấm - trong trường hợp này trình biên dịch không biết có bao nhiêu byte để đọc sau địa chỉ.

4

Chết đơn giản:

void* p; 
*p; // compile error! 

Hoặc để đặt nó trong lời nói; một con trỏ void không thể được dereferenced.

Có lẽ bạn nên đổi tên câu hỏi tại sao chúng ta có con trỏ, hay đúng hơn là không và chỉ tìm kiếm câu hỏi đó trên SO.

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