【问题标题】:Make C floating point literals float (rather than double)使 C 浮点文字浮动(而不是双精度)
【发布时间】:2015-11-22 20:50:14
【问题描述】:

众所周知,在 C 语言中,浮点字面量(例如 1.23)的类型为 double。因此,任何涉及它们的计算都会被提升为双倍。

我正在开发一个嵌入式实时系统,该系统具有一个仅支持单精度 (float) 数字的浮点单元。我所有的变量都是float,这个精度就足够了。我根本不需要(也买不起)double。但每次都像

if (x < 2.5) ...

写了,灾难发生了:减速可能高达两个数量级。当然,直接的答案就是写

if (x < 2.5f) ...

但这很容易被忽略(并且很难检测到,直到为时已晚),尤其是当“配置”值是 #define'd 由不那么训练的(或只是新的)开发人员在单独的文件中时。

那么,有没有办法强制编译器将所有(浮点)文字视为浮点数,就好像带有后缀f 一样?即使它违反规格,我也不在乎。还是有其他解决方案?顺便说一句,编译器是 gcc。

【问题讨论】:

  • -Wdouble-promotion,它至少会给你警告。结合-Wfloat-conversion 应该可以提供很好的覆盖率。
  • 这并不能直接回答你的问题,但是编写一个脚本来插入任何缺失的fs 从 FP 文字中并不难。
  • 一些用于嵌入式系统的编译器将双精度映射为浮点,并且仅通过选项启用双精度。不知道GCC里有没有类似的东西
  • @BrettHale 该评论值得作为正确答案。我认为在这种情况下获得警告会比其他一些允许程序员编写与标准不兼容的代码的编译器选项更有效率。

标签: c gcc floating-point literals


【解决方案1】:

-fsingle-precision-constant 标志可以使用。它会导致浮点常量以单精度加载​​,即使这并不精确。

注意 - 这也将在对双精度变量的操作中使用单精度常量。

【讨论】:

  • 谢谢!我不知道这面旗帜。这完美地回答了我的问题 - 尽管正如其他人所建议的那样,生成警告可能会更谨慎。
  • @Zeus 很高兴它有帮助! :)
  • 我会明智地使用这个选项!考虑一个新开发人员,只需输入x &lt; 2.5,一切都会好起来的。他可能会错过挽救他生命的特定编译器选项:-)。当他收到警告时(使用-Wdouble-promotion-Wfloat-conversion),而您使用将所有警告转换为错误的-Werror,他可能不会直接签入代码,并且可能会想知道并学习。但只是为了发布质量,您可能希望安全起见,并使用特定选项 (-fsingle-precision-constant) 编译它。请注意,这只是一条评论。
【解决方案2】:

改用警告:-Wdouble-promotion 警告 implicit float to double Promotion,如您的示例所示。 -Wfloat-conversion 将警告您可能仍在为浮点数分配双精度值的情况。

与简单地将双精度值强制为最接近的浮点值相比,这是一个更好的解决方案。您的浮点代码仍然是合规的,如果双精度值保持正值,例如小于 FLT_DENORM_MIN(假设为 IEEE-754)或大于 FLT_MAX,您不会得到任何令人讨厌的惊喜。

【讨论】:

  • 当然,总的来说你是对的。但是,在我的具体情况下,-fsingle-precision-constant 效果更好。首先,我的 GCC (4.4.7) 版本根本没有这些选项中的任何一个。其次,我没有任何棘手的常数(除了 NaN),所有计算都必须是 float 无论如何(这就是重点)。最后,提供的芯片库会生成如此多的警告(其中大部分是明确的!),有用的警告经常被埋没……而且,正如我所说,在这种情况下,我不太关心严格遵守。
  • 我也相信使用命令开关隐藏源代码中的问题是很危险的。只需考虑五年后其他人可能会使用您的代码使用新版本的编译器,也许没有那个整洁的开关。修复源代码中的问题比隐藏它们要好得多。关于所有这些警告......在为生产编译时,警告应该被视为错误。 -错误:-)
  • 强迫自己在 每个 数字文字的末尾写上f 并不明智,
  • @12Me21 :查看 float fn (float x) { return (x * 1.2); }(1.2f) 的 asm 输出 - 表达式被强制计算为双精度,然后转换回浮点数。这不是“聪明”的问题。
  • 哦,我的意思是,我觉得 -fsingle-precision-constant 在这里是一个更好的解决方案。以更少的努力获得相同的结果。
【解决方案3】:

您可以将定义的常量转换为(float),无论它们在哪里使用,优化器都应该完成它的工作。这是一个便携式解决方案。

#define LIMIT 2.5

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

【讨论】:

  • 或者在定义中强制转换,如#define foo ((float) 1.234)
  • @CuriousRabbit:这并没有解决“缺乏纪律(或只是新的)开发人员”的问题。
【解决方案4】:

-Wunsuffixed-float-constants 标志也可以使用,可能与上面接受的答案中的一些其他选项结合使用。但是,这可能不会捕获系统标头中的无后缀常量。也需要使用-Wsystem-headers 来捕捉它们。可能会产生很多警告...

【讨论】:

    猜你喜欢
    • 2017-04-22
    • 1970-01-01
    • 2018-07-06
    • 2011-05-18
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多