2013-10-10 14 views
6

Là cố vấn bởi một câu trả lời ở đây, tôi bật -Wbad-function-cast để xem mã của tôi có bất kỳ xấu hành vi gcc có thể nắm bắt, và nó bật lên ví dụ này:Mục đích của gcc -Wbad-function-cast là gì?

unsigned long n; 
// ... 
int crossover = (int)pow(n, .14); 

(nó không quan trọng ở đây là crossover là một int ; nó có thể là unsigned long và thông báo sẽ giống nhau).

Điều này có vẻ giống như một ví dụ khá bình thường và hữu ích về dàn diễn viên. Tại sao điều này có vấn đề? Nếu không, có lý do nào để giữ cảnh báo này được bật không?

Tôi thường muốn đặt nhiều cảnh báo, nhưng tôi không thể che giấu đầu óc xung quanh trường hợp sử dụng cho trường hợp này. Mã tôi đang làm việc trên là rất nhiều số và có rất nhiều lần mà mọi thứ được đúc từ một loại khác theo yêu cầu để đáp ứng nhu cầu khác nhau của các thuật toán có liên quan.

Trả lời

1

Tiện ích của cảnh báo -Wbad-function-cast bị giới hạn.

Có thể, không phải ngẫu nhiên mà không phải -Wall cũng không phải -Wextra bật cảnh báo đó. Cũng như nó không có sẵn cho C++ (nó chỉ là C/Objective-C).

Ví dụ cụ thể của bạn không khai thác hành vi không xác định cũng như hành vi được xác định thực hiện (xem ISO C11, Mục 6.3.1.4). Do đó, cảnh báo này cho bạn lợi ích không.

Ngược lại, nếu bạn cố gắng viết lại mã của bạn để làm cho -Wbad-function-cast hạnh phúc bạn chỉ cần thêm chức năng không cần thiết gọi mà thậm chí gần đây GCC/Clang compilers don't optimize away với -O3:

#include <math.h> 
#include <fenv.h> 
int f(unsigned n) 
{ 
    int crossover = lrint(floor(pow(n, .14))); 
    return crossover; 
} 

(ví dụ tiêu cực, no warning emitted với -Wbad-function-cast nhưng các cuộc gọi chức năng không cần thiết)

5

Bạn nên thực hiện cảnh báo này một cách nghiêm túc.

Nếu bạn muốn lấy số nguyên từ kết quả dấu phẩy động của pow, đó là thao tác làm tròn, phải được thực hiện với một trong các chức năng làm tròn tiêu chuẩn như round. Làm điều này với số nguyên cast có thể mang lại bất ngờ: bạn thường mất phần phân đoạn và ví dụ 2.76 có thể kết thúc là 2 với cắt ngắn số nguyên, giống như 2.12 sẽ kết thúc là 2. Ngay cả khi bạn muốn hành vi này, bạn nên xác định rõ ràng hơn với hàm floor. Điều này sẽ tăng khả năng đọc và hỗ trợ mã của bạn.

+0

Có, tôi muốn hành vi đó, đó là lý do tôi truyền. Tôi nhận thấy rằng tôi nhận được mã chậm hơn khi tôi thêm 'tầng'; đặc biệt, tôi nhận được 'roundsd' rồi' cvttsd2si' tại -O3 thay vì chỉ đơn giản là 'cvttsd2si'. Điều này có làm gì cho tôi không? (Tôi sẵn sàng trả tiền phạt hiệu suất - mặc dù ứng dụng này nhạy cảm với tốc độ, phần đặc biệt này nằm ngoài vòng lặp nóng - nhưng chỉ khi nó sẽ làm điều gì đó có giá trị.) – Charles

+0

Nếu bạn đang (1) nhắm mục tiêu một kiến ​​trúc cụ thể và (2) hiểu bạn đang làm gì với việc cắt xén ở đây, sau đó bạn có thể bỏ qua hoặc tắt cảnh báo này. Nó được ban hành trong C để cảnh báo về khả năng tương thích nền tảng và các vấn đề làm tròn. Ngoài ra nếu kết quả gấp đôi của pow tràn giá trị số nguyên tối đa, thì hành vi truyền là không xác định, trong khi hành vi sàn luôn được chỉ định. –

+0

Tôi đồng ý rằng tràn sẽ cung cấp cho hành vi không xác định, đó là một điều xấu. (Đó là lý do tại sao tôi đã cung cấp mã mẫu của tôi - bạn có thể thấy rằng tràn không thể có ở đây.) Cảm ơn, tôi đang chấp nhận ngay bây giờ. – Charles

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