Tôi đưa vào dàn diễn viên chỉ đơn giản là thể hiện sự không tán thành lỗ hổng xấu xí trong hệ thống loại, cho phép mã như đoạn mã sau để biên dịch mà không cần chẩn đoán, mặc dù không có phôi nào được sử dụng để mang lại chuyển đổi xấu:
double d;
void *p = &d;
int *q = p;
Tôi ước điều đó không tồn tại (và nó không có trong C ++) và vì vậy tôi đã chọn. Nó đại diện cho sở thích của tôi, và chính trị lập trình của tôi. Tôi không chỉ đúc một con trỏ, mà còn hiệu quả, bỏ phiếu, và đuổi quỷ ngu ngốc . Nếu tôi thực sự không thể thể hiện sự ngu ngốc , thì ít nhất hãy để tôi bày tỏ mong muốn làm điều đó bằng một cử chỉ phản kháng.
Trong thực tế, một cách thực hành tốt là bọc malloc
(và bạn bè) với các hàm trả về unsigned char *
và về cơ bản không bao giờ sử dụng void *
trong mã của bạn. Nếu bạn cần một con trỏ chung cho bất kỳ đối tượng nào, hãy sử dụng một char *
hoặc unsigned char *
và có các phôi theo cả hai hướng. Một thư giãn có thể được thưởng thức, có lẽ, là sử dụng các chức năng như memset
và memcpy
không có phôi.
Về chủ đề truyền và tương thích C ++, nếu bạn viết mã của mình để nó biên dịch thành cả C và C ++ (trong trường hợp đó bạn phải truyền giá trị trả về malloc
khi gán nó cho một thứ khác void *
), bạn có thể làm rất hữu ích điều cho bản thân bạn: bạn có thể sử dụng các macro để truyền mà dịch sang các kiểu kiểu C ++ khi biên dịch thành C ++, nhưng giảm xuống thành một biểu tượng C khi biên dịch thành C:
/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif
Nếu bạn tuân thủ các macro này, thì một grep
tìm kiếm đơn giản về cơ sở mã của bạn cho các mã định danh này sẽ cho bạn biết vị trí của tất cả các phôi của bạn, vì vậy bạn có thể xem lại bất kỳ trong số chúng là không chính xác.
Sau đó, về phía trước, nếu bạn thường xuyên biên dịch mã bằng C ++, nó sẽ thực thi việc sử dụng một dàn diễn viên phù hợp. Chẳng hạn, nếu bạn strip_qual
chỉ sử dụng để loại bỏ một const
hoặc volatile
, nhưng chương trình thay đổi theo cách liên quan đến chuyển đổi loại, bạn sẽ nhận được chẩn đoán và bạn sẽ phải sử dụng kết hợp các phôi để có được chuyển đổi mong muốn.
Để giúp bạn tuân thủ các macro này, trình biên dịch GNU C ++ (không phải C!) Có một tính năng tuyệt vời: một chẩn đoán tùy chọn được tạo cho tất cả các lần xuất hiện của kiểu phôi C.
-Wold-style-cast (chỉ C ++ và Objective-C ++)
Cảnh báo nếu sử dụng kiểu cũ (kiểu C) sang loại không trống
trong một chương trình C ++. Các phôi kiểu mới (Dynamic_cast,
static_cast, reinterpret_cast và const_cast) ít bị tổn thương hơn
để các hiệu ứng ngoài ý muốn và dễ dàng hơn để tìm kiếm.
Nếu mã C của bạn biên dịch thành C ++, bạn có thể sử dụng -Wold-style-cast
tùy chọn này để tìm hiểu tất cả các lần xuất hiện của (type)
cú pháp truyền có thể len vào mã và theo dõi các chẩn đoán này bằng cách thay thế nó bằng một lựa chọn thích hợp trong số các macro trên (hoặc một kết hợp, nếu cần thiết).
Cách xử lý chuyển đổi này là biện minh kỹ thuật độc lập lớn nhất để làm việc trong "Clean C": phương ngữ C và C ++ kết hợp, về mặt kỹ thuật biện minh cho việc đúc giá trị trả về malloc
.