Làm cho các ký tự dấu phẩy động C nổi (thay vì gấp đôi)


76

Ai cũng biết rằng trong C, các ký tự dấu phẩy động (ví dụ 1.23) có kiểu double. Kết quả là, bất kỳ phép tính nào liên quan đến chúng đều được tăng gấp đôi.

Tôi đang làm việc trên một hệ thống thời gian thực được nhúng có đơn vị dấu phẩy động chỉ hỗ trợ các số chính xác ( float) duy nhất . Tất cả các biến của tôi là đủ float, và độ chính xác này là đủ. Tôi không cần (cũng như không đủ khả năng) doublechút nào. Nhưng mỗi khi một cái gì đó như

được viết, thảm họa xảy ra: sự chậm lại có thể lên đến hai bậc của cường độ. Tất nhiên, câu trả lời trực tiếp là viết

nhưng điều này rất dễ bị bỏ sót (và khó phát hiện cho đến khi quá muộn), đặc biệt là khi giá trị 'cấu hình' nằm #definetrong một tệp riêng biệt của một nhà phát triển kém kỷ luật (hoặc chỉ mới).

Vì vậy, có cách nào để buộc trình biên dịch coi tất cả các ký tự (dấu phẩy động) là float, như thể với hậu tố f? Ngay cả khi nó chống lại các thông số kỹ thuật, tôi không quan tâm. Hoặc bất kỳ giải pháp nào khác? Nhân tiện, trình biên dịch là gcc.


30
-Wdouble-promotion, điều này ít nhất sẽ cung cấp cho bạn cảnh báo. Kết hợp với -Wfloat-conversionnên cho độ che phủ khá tốt.
Brett Hale

3
Điều này không trực tiếp trả lời câu hỏi của bạn, nhưng sẽ không khó để viết một tập lệnh chỉ chèn bất kỳ chữ cái nào còn thiếu ftừ các ký tự FP.
Xophmeister

1
Điều này có hữu ích không: stackoverflow.com/questions/24688911/… ?
Rahul Tripathi

4
Một số trình biên dịch cho các hệ thống nhúng ánh xạ kép thành float và chỉ kích hoạt độ chính xác kép với một tùy chọn. Tôi không biết nếu có một cái gì đó tương tự trong GCC
phuclv

3
@BrettHale Nhận xét đó xứng đáng là một câu trả lời xác đáng. Tôi nghĩ rằng nhận được cảnh báo trong trường hợp này sẽ hiệu quả hơn một số tùy chọn trình biên dịch khác cho phép lập trình viên viết mã không tương thích với tiêu chuẩn.
user694733

Câu trả lời:


83

-fsingle-precision-constantcờ có thể được sử dụng. Nó làm cho các hằng số dấu phẩy động được tải với độ chính xác duy nhất ngay cả khi điều này không chính xác.

Lưu ý- Điều này cũng sẽ sử dụng hằng số chính xác đơn trong các hoạt động trên biến chính xác kép.


2
Cảm ơn! Tôi không biết về lá cờ này. Điều này trả lời câu hỏi của tôi một cách hoàn hảo - mặc dù, như những người khác đã đề xuất, việc tạo ra các cảnh báo có lẽ sẽ cần thận trọng hơn.
Zeus,

@Zeus Rất vui vì nó đã giúp được !! :)
ameyCU

2
Tôi sẽ sử dụng tùy chọn này một cách khôn ngoan! Hãy xem xét một nhà phát triển mới, chỉ cần gõ x < 2.5, mọi thứ sẽ ổn. Anh ta có khả năng bỏ lỡ tùy chọn trình biên dịch cụ thể đó đã cứu mạng anh ta :-). Thay vào đó -Wdouble-promotion, khi anh ta nhận được cảnh báo (với , -Wfloat-conversion) và bạn sử dụng -Werrorđiều này để chuyển tất cả cảnh báo thành lỗi, anh ta có thể không trực tiếp kiểm tra mã và có thể thắc mắc và tìm hiểu. Nhưng chỉ vì chất lượng bản phát hành, bạn có thể muốn chơi an toàn và biên dịch nó với tùy chọn cụ thể ( -fsingle-precision-constant). Xin lưu ý rằng đây chỉ là một bình luận.
toán học

52

Thay vào đó, hãy sử dụng các cảnh báo: -Wdouble-promotioncảnh báo về quảng cáo chuyển thành kép ngầm , như trong ví dụ của bạn. -Wfloat-conversionsẽ cảnh báo về các trường hợp mà bạn vẫn có thể chỉ định các cú đúp cho phao.

Đây là một giải pháp tốt hơn là chỉ buộc các giá trị kép về giá trị float gần nhất. Mã dấu phẩy động của bạn vẫn tuân thủ và bạn sẽ không nhận được bất kỳ sự ngạc nhiên khó chịu nào nếu một giá trị kép giữ một giá trị dương, chẳng hạn, nhỏ hơn FLT_DENORM_MIN(giả sử IEEE-754) hoặc lớn hơn FLT_MAX.


Tất nhiên, bạn nói chung là đúng. Tuy nhiên, trong hoàn cảnh cụ thể của tôi -fsingle-precision-constanthoạt động tốt hơn. Đầu tiên, phiên bản GCC (4.4.7) của tôi chỉ đơn giản là không có một trong hai tùy chọn này. Thứ hai, tôi không có bất kỳ hằng số phức tạp nào (ngoài NaN) và tất cả các phép tính floatdù sao cũng phải như vậy (đây là toàn bộ điểm). Cuối cùng, thư viện chip được cung cấp tạo ra rất nhiều cảnh báo (hầu hết đều rõ ràng!) Mà những cái hữu ích thường bị chôn vùi trong đống ... Và, như tôi đã nói, tôi không quan tâm lắm về việc tuân thủ nghiêm ngặt trong trường hợp này.
Zeus,

2
Tôi cũng tin rằng thật nguy hiểm nếu chỉ ẩn một vấn đề trong mã nguồn của bạn bằng cách sử dụng công tắc lệnh. Chỉ cần xem xét rằng mã của bạn có thể được người khác sử dụng trong 5 năm kể từ bây giờ bằng cách sử dụng phiên bản mới của trình biên dịch, có thể không có công tắc gọn gàng đó. Việc khắc phục các vấn đề trong mã nguồn sẽ tốt hơn là ẩn chúng. Và về tất cả những cảnh báo này ... khi biên dịch để sản xuất, các cảnh báo nên được coi là lỗi.
-Werror

1

Bạn có thể truyền các hằng số đã xác định đến (float)bất cứ nơi nào chúng được sử dụng, trình tối ưu hóa sẽ thực hiện công việc của nó. Đây là một giải pháp di động.


Hoặc truyền chúng theo định nghĩa, như trong #define foo ((float) 1.234)
CuriousRabbit.

2
@CuriousRabbit: điều đó không giải quyết vấn đề "một nhà phát triển kém kỷ luật (hoặc chỉ mới)".
Yves Daoust

1

Các -Wunsuffixed-float-constantslá cờ có thể được sử dụng quá, có thể kết hợp với một số tùy chọn khác trong câu trả lời được chấp nhận ở trên. Tuy nhiên, điều này có thể sẽ không bắt được các hằng số không cố định trong tiêu đề hệ thống. Sẽ cần phải sử dụng -Wsystem-headersđể bắt những người quá. Có thể tạo ra nhiều cảnh báo ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.