Mã của bạn có thể hoạt động trên một số nền tảng nhưng không thể di động được. Lý do là C không có con trỏ chung cho kiểu con trỏ. Trong trường hợp của void *
tiêu chuẩn cho phép rõ ràng chuyển đổi giữa nó và con trỏ khác để hoàn thành/không đầy đủ các loại, nhưng đây không phải là trường hợp với void **
. Điều này có nghĩa là trong mã của bạn, trình biên dịch không có cách nào biết được giá trị của *vp
đã được chuyển đổi từ bất kỳ loại nào khác ngoài void *
và do đó không thể thực hiện bất kỳ chuyển đổi nào ngoại trừ chuyển đổi bạn tự cast.
xem xét mã này:
void dont_do_this(struct a_t **a, struct b_t **b)
{
void **x = (void **) a;
*x = *b;
}
Trình biên dịch sẽ không phàn nàn về diễn viên tiềm ẩn b_t *
-void *
trong dòng *x = *b
, mặc dù dòng đó đang cố gắng đưa một con trỏ đến một b_t
ở một nơi mà chỉ cần trỏ đến a_t
. Sai lầm là trong thực tế trong dòng trước đó, đó là chuyển đổi "một con trỏ đến một nơi mà con trỏ đến a_t
có thể được đặt" để "một con trỏ đến một nơi mà con trỏ đến bất cứ điều gì có thể được đặt". Đây là lý do không có diễn viên tiềm ẩn có thể. Để có ví dụ tương tự với con trỏ cho các loại số học, hãy xem C FAQ.
Tác vụ của bạn, sau đó, mặc dù nó tắt cảnh báo trình biên dịch, rất nguy hiểm vì không phải tất cả các loại con trỏ đều có cùng kích thước/biểu diễn bên trong (ví dụ: void **
và int *
). Để làm cho mã của bạn hoạt động trong mọi trường hợp, bạn phải sử dụng một số trung gian void *
:
int *array;
void *varray = array;
void **vp = &varray;
*vp = malloc(sizeof(int) * 10);
Nguồn
2013-08-31 20:16:27
Bạn có nghĩa là gì 'int *' đang truy cập "mặc dù một loại"? – ash
Eli Bendersky có bài đăng trên blog về chủ đề này: http://eli.thegreenplace.net/2009/11/16/void-and-casts-in-c-and-c/ –
@MortenJensen dường như chỉ thảo luận về khoảng trống * và không void ** –