2013-06-07 41 views
13

Là mới đối với C, cách sử dụng thực tế duy nhất tôi đã loại bỏ các con trỏ void là cho các chức năng linh hoạt có thể lưu trữ các kiểu dữ liệu khác nhau trong một con trỏ nhất định. Vì vậy, tôi đã không gõ con trỏ của tôi khi thực hiện cấp phát bộ nhớ.Tại sao nên nhập con trỏ trống?

Tôi đã thấy một số ví dụ mã đôi khi sử dụng con trỏ void, nhưng chúng có kiểu đúc. Tại sao điều này hữu ích? Tại sao không trực tiếp tạo loại con trỏ mong muốn thay vì một khoảng trống?

+6

Bạn có thể hiển thị ví dụ không? –

+3

Bạn không cần truyền từ 'void *' vì ngôn ngữ xác định chuyển đổi tự động từ 'void *' sang bất kỳ kiểu con trỏ nào khác, nhưng không phải tất cả các lập trình viên đều biết điều này (thậm chí không phải tất cả tác giả sách C) . –

+0

Bạn phải bỏ một con trỏ rỗng nếu bạn muốn truy cập cấu trúc của nó. (Struct) –

Trả lời

6

Bạn cần phải cast con trỏ void đến cái gì khác nếu bạn muốn dereference họ, ví dụ bạn có được một con trỏ void như một tham số chức năng và bạn biết chắc chắn đây là một số nguyên:

void some_function(void * some_param) { 
    int some_value = *some_param; /* won't work, you can't dereference a void pointer */ 
} 

void some_function(void * some_param) { 
    int some_value = *((int *) some_param); /* ok */ 
} 
+1

Bạn không * cần; * a cách tiếp cận dễ đọc hơn (được ưa thích bởi tôi) là 'int * tmp = param; int val = * tmp; '. –

+0

@ H2CO3 Bạn phải chọn nếu con trỏ là loại void. Như trong ví dụ của Guillaume. –

+1

@Armin Bạn không cần phải **, tôi lặp lại - có thể tránh được nếu bạn chỉ định con trỏ tạm thời. –

1

khoảng trống của bạn con trỏ có thể đại diện cho một số loại phức tạp hơn, chẳng hạn như cấu trúc bạn sẽ cần phải dereference để truy cập là thành viên.

typedef struct CombinedData 
{ 
    int memberA; 
    double memberB; 
} CombinedData; 

void fun(void* data) 
{ 
    CombinedData* p = (CombinedData*)data; 
    doSomethingWith(p->memberA, p->memberB);   
} 
+2

Như những người khác đã nói, bạn không cần phải truyền một cách rõ ràng 'dữ liệu' của bạn trước bài tập. Một điểm khác là mã của bạn bị hỏng cho trình biên dịch * C * (không phải là một C++): 'CombinedData * p' →' struct CombinedData * p'. – firegurafiku

+1

@firegurafiku Thats một điểm rất tốt, tôi sẽ cập nhật các bài viết để sử dụng một typedef-ed struct. Đó là một thời gian dài kể từ khi tôi trả lời câu hỏi này và tôi hoàn toàn không thể nhớ được liệu tôi có nhận ra đó là câu C hay không và không phải là câu hỏi C++. – DuncanACoulter

12

Có hai lý do cho đúc một con trỏ void thành một kiểu khác trong C.

  1. Nếu bạn muốn truy cập một cái gì đó được trỏ đến bởi con trỏ (*(int*)p = 42)
  2. Nếu bạn đang thực sự viết mã trong tập hợp con chung của C và C++, chứ không phải là "thực" C. Xem thêm Do I cast the result of malloc?

Lý do cho 1 phải rõ ràng. Số hai là vì C++ không cho phép chuyển đổi ngầm từ void* sang các loại khác, trong khi C cho phép nó.

+1

Nhưng đối số 2 không hợp lệ: không nên biên dịch mã C bằng trình biên dịch C++. –

+5

@ H2Co3: Đúng, nhưng đôi khi bạn có mã được xác định trong tệp tiêu đề trong macro hoặc hàm nội tuyến có nghĩa là có thể sử dụng được trong cả mã C và C++ bao gồm các tiêu đề đó. –

+1

@ H2CO3 Tuy nhiên, một số người làm điều đó. Tôi đang cố giải thích hiện tượng này, không biện minh cho nó. – wolfgang

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