Зробіть літерали з плаваючою комою C плаваючими (а не подвійними)


76

Добре відомо, що в C літерали з плаваючою комою (наприклад 1.23) мають тип double. Як наслідок, будь-який розрахунок, який їх включає, підвищується вдвічі.

Я працюю над вбудованою системою реального часу, яка має одиницю з плаваючою комою, яка підтримує лише одиничні floatчисла точності ( ). Усі мої змінні є float, і цієї точності достатньо. Мені взагалі не потрібно (і не по кишені) double. Але кожного разу щось на кшталт

написано, трапляється катастрофа: уповільнення може становити до двох порядків. Звичайно, пряма відповідь - писати

але це так легко пропустити (і важко виявити до пізнього часу), особливо коли значення "конфігурації" #defineв окремому файлі належить менш дисциплінованому (або просто новому) розробнику.

Отже, чи є спосіб змусити компілятор обробляти всі літерали (з плаваючою комою) як плаваючі, ніби із суфіксом f? Навіть якщо це суперечить специфікаціям, мені все одно. Або будь-які інші рішення? До речі, компілятор - gcc.


30
Є -Wdouble-promotion, що принаймні дасть вам попередження. У поєднанні з -Wfloat-conversionмає дати досить хороше покриття.
Brett Hale

3
Це не відповідає безпосередньо на ваше запитання, але не складно буде написати сценарій, щоб просто вставити будь-які відсутні fs з літералів FP.
Xophmeister


4
Деякі компілятори для вбудованих систем поєднують подвійний плаваючий і дозволяють подвійну точність лише з опцією. Я не знаю, чи є щось подібне в GCC
phuclv

3
@BrettHale Цей коментар гідний належної відповіді. Я думаю, що отримання попереджень у цьому випадку було б більш продуктивним, ніж якийсь інший варіант компілятора, який дозволяє програмісту писати код, який не сумісний зі стандартом.
user694733

Відповіді:


83

-fsingle-precision-constantможна використовувати прапор. Це змушує константи з плаваючою точкою завантажуватися з однією точністю, навіть коли це не точно.

Примітка. Це також використовуватиме одиничні константи точності в операціях із змінними подвійної точності.


2
Дякую! Я не знав про цей прапор. Це ідеально відповідає на моє запитання - хоча, як і припускають інші, попередження може бути більш розумним.
Зевс,

@Zeus Радий, що це допомогло !! :)
ameyCU

2
Я б використав цей варіант з розумом! Подумайте про нового розробника, просто набравши x < 2.5, все буде гаразд. Ймовірно, він пропустить той конкретний варіант компілятора, який рятує йому життя :-). Коли він замість цього отримує попередження (за допомогою -Wdouble-promotion, -Wfloat-conversion), і ви використовуєте, -Werrorщо перетворює всі попередження в помилки, він може не перевіряти код безпосередньо, а може дивуватися і вчитися. Але тільки для якості випуску, ви можете захотіти грати в безпеці та скомпілювати його з певним параметром ( -fsingle-precision-constant). Зверніть увагу, це лише коментар.
математика

52

Замість цього використовуйте попередження: -Wdouble-promotionпопереджає про неявний float для подвійного просування, як у вашому прикладі. -Wfloat-conversionпопереджатиме про випадки, коли ви все ще можете призначати дублі для плаваючих.

Це краще рішення, ніж просто примусове подвійне значення до найближчого плаваючого значення. Ваш код із плаваючою комою все ще відповідає вимогам, і ви не отримаєте неприємних сюрпризів, якщо подвійне значення має позитивне значення, скажімо, менше ніж FLT_DENORM_MIN(припускаючи IEEE-754) або більше ніж FLT_MAX.


Ви загалом маєте рацію, звичайно. Однак у моїх конкретних обставинах це -fsingle-precision-constantпрацює краще. По-перше, у моїй версії GCC (4.4.7) просто немає жодного з цих варіантів. По-друге, у мене немає ніяких хитрих констант (крім NaN), і всі обчислення floatвсе одно мають бути (це вся суть). Нарешті, надана бібліотека чіпів генерує стільки попереджень (більшість із них явних!), Що корисні часто закопуються в купу ... І, як я вже сказав, мене не дуже турбує суворе дотримання в цьому випадку.
Зевс

2
Я теж вважаю, що небезпечно просто приховувати проблему, яка є у вашому вихідному коді, за допомогою командного перемикача. Просто врахуйте, що ваш код може використовуватися кимось іншим через п’ять років, використовуючи нову версію компілятора, можливо, не маючи цього акуратного перемикача. Набагато краще виправити проблеми у вихідному коді, ніж приховувати їх. І про всі ці попередження ... при складанні для виробництва попередження слід вважати помилками. -Помилка :-)
ChrisB

1

Ви можете передавати визначені константи туди, (float)де вони використовуються, оптимізатор повинен виконувати свою роботу. Це портативне рішення.


Або додайте їх у визначення, як у #define foo ((float) 1.234)
CuriousRabbit

2
@CuriousRabbit: це не стосується питання "менш дисциплінованого (або просто нового) розробника".
Yves Daoust

1

-Wunsuffixed-float-constantsПрапор може бути використаний також, можливо , в поєднанні з деякими з інших варіантів в загальноприйнятому відповідь вище. Однак це, ймовірно, не вловить несуфіксовані константи в заголовках системи. Потрібно було б використовувати, -Wsystem-headersщоб зловити їх теж. Може створити багато попереджень ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.