ChatGPT解决这个技术问题 Extra ChatGPT

Make C floating point literals float (rather than double)

It is well known that in C, floating point literals (e.g. 1.23) have type double. As a consequence, any calculation that involves them is promoted to double.

I'm working on an embedded real-time system that has a floating point unit that supports only single precision (float) numbers. All my variables are float, and this precision is sufficient. I don't need (nor can afford) double at all. But every time something like

if (x < 2.5) ...

is written, disaster happens: the slowdown can be up to two orders of magnitude. Of course, the direct answer is to write

if (x < 2.5f) ...

but this is so easy to miss (and difficult to detect until too late), especially when a 'configuration' value is #define'd in a separate file by a less disciplined (or just new) developer.

So, is there a way to force the compiler to treat all (floating point) literals as float, as if with suffix f? Even if it's against the specs, I don't care. Or any other solutions? The compiler is gcc, by the way.

There's -Wdouble-promotion, which will at least give you warnings. Combined with -Wfloat-conversion should give pretty good coverage.
This doesn't directly answer your question, but it wouldn't be that difficult to write a script to just insert any missing fs from FP literals.
Some compilers for embedded systems map double to float and only enable double precision with an option. I don't know if there are something similar in GCC
@BrettHale That comment is worthy of being an proper answer. I think that getting warnings in this case would be more productive, than some other compiler option that allows programmer to write code that's not compatible with the standard.

a
ameyCU

-fsingle-precision-constant flag can be used. It causes floating-point constants to be loaded in single precision even when this is not exact.

Note- This will also use single precision constants in operations on double precision variables.


Thanks! I didn't know about this flag. This answers my question perfectly - even though, as other suggested, generating warnings would perhaps be more prudent.
@Zeus Glad it helped !! :)
I would use this option wisely! Consider a new developer, just typing x < 2.5, everything will be okay. He is likely to miss that specific compiler option which saves his life :-). When he is getting warnings instead (with -Wdouble-promotion, -Wfloat-conversion), and you use -Werror which converts all warnings into errors, he may not directly checkin the code, and might wonder, and learn. But just for release quality, you might want to play safe, and compile it with the specific option (-fsingle-precision-constant). Please note this is just a comment.
B
Brett Hale

Use warnings instead: -Wdouble-promotion warns about implicit float to double promotion, as in your example. -Wfloat-conversion will warn about cases where you may still be assigning doubles to floats.

This is a better solution than simply forcing double values to the nearest float value. Your floating-point code is still compliant, and you won't get any nasty surprises if a double value holds a positive value, say, less than FLT_DENORM_MIN (assuming IEEE-754) or greater than FLT_MAX.


You are right in general, of course. However, in my specific circumstances -fsingle-precision-constant works better. First, my version of GCC (4.4.7) simply doesn't have either of these options. Second, I don't have any tricky constants (apart from NaN), and all calculations must be float anyway (this is the whole point). Finally, the supplied chip library generates so many warnings (most of them explicit!) that the useful ones often get buried in the pile... And, as I said, I'm not very concerned about strict compliance in this case.
I, too, believe that it is dangerous to just hide a problem that is in your source code using a command switch. Just consider that your code might be used by someone else five years from now using a new version of the compiler, maybe not having that neat switch. It is much preferable to fix the problems in the source code than to hide them. And about all these warnings... when compiling for production, warnings should be considered errors. -Werror :-)
there's nothing smart about forcing yourself to write f at the end of every number literal,
@12Me21 : look at the asm output of: float fn (float x) { return (x * 1.2); } vs (1.2f) - the expression is forced to be evaluated as a double and then converted back to a float. It's not a question of being 'smart'.
oh I just meant, I feel like -fsingle-precision-constant is a better solution here. same result with less effort.
Y
Yves Daoust

You can cast the defined constants to (float) wherever they are used, the optimizer should do its job. This is a portable solution.

#define LIMIT 2.5

if (x < (float)LIMIT) ...

Or cast them in the definition, as in #define foo ((float) 1.234)
@CuriousRabbit: that doesn't address the "a less disciplined (or just new) developer" issue.
d
delsauce

The -Wunsuffixed-float-constants flag could be used too, maybe combined with some of the other options in the accepted answer above. However, this probably won't catch unsuffixed constants in system headers. Would need to use -Wsystem-headers to catch those too. Could generate a lot of warnings...