【问题标题】:sqrt() of int type in CC 中 int 类型的 sqrt()
【发布时间】:2012-11-01 13:58:00
【问题描述】:

我在 mac os x 上用 c 语言编程。我正在使用来自 math.h 的 sqrt,函数如下:

int start = Data -> start_number;
double localSum;

for (start; start <= end; start++) {
    localSum += sqrt(start);
}

这行得通,但为什么呢?为什么我没有收到警告?在 sqrt 的手册页上,它需要一个 double 作为参数,但我给它一个 int - 它是如何工作的?

谢谢

【问题讨论】:

    标签: c int double sqrt


    【解决方案1】:

    不会导致精度损失的类型转换可能不会引发警告。它们是隐式转换的。

    int --> double //no loss in precision (e.g 3 became 3.00)
    double --> int //loss in precision (e.g. 3.01222 became 3)
    

    什么触发警告,什么不触发在很大程度上取决于编译器和提供给它的标志,但是,大多数编译器(至少我使用过的那些)不考虑隐式type-conversions dangerous 足以引起警告,因为它是语言规范中的一项功能。


    警告还是不警告:

    C99 Rationale 将其表述为指南

    探索这个(隐式转换)问题的重要成果之一是了解高质量编译器可能会很好地查找 对于此类有问题的代码并提供(可选)诊断,并且 尽职尽责的讲师可能会很好地警告程序员 隐式类型转换的问题。

    C99 Rationale (Apr 2003) : Page 45

    【讨论】:

    • “因为它没有列出从 int 到 double 的转换” 它确实有,例如在 C99 的 6.3.1 子句中。我不知道 eli-project 是什么,但要么你误解了它的含义,要么它还不是 C 标准的准确形式化。
    • 我认为是 C89,称为 ANSI C
    • 好的,我会试着解开它。 6.5.2.2:4 参数可以是任何对象类型的表达式。在准备调用函数时,会计算参数,并为每个参数分配相应参数的值。
    • 6.3.1.4:2 当整数类型的值转换为真正的浮点类型时,如果被转换的值可以在新的类型中精确表示,则保持不变。如果要转换的值在可以表示但不能准确表示的值范围内,则结果是最接近的较高或最近的较低可表示值,以实现定义的方式选择。如果要转换的值超出可表示的值范围,则行为未定义。
    • 如果你喜欢这类事情,C11 的一个最近且准确的形式化是 code.google.com/p/c-semantics 。我没看过,但我用过从它的规则派生的解释器。
    【解决方案2】:

    编译器知道sqrt 的原型,因此它可以并且将在调用函数之前生成将int 参数转换为double 的代码。

    反之亦然,如果您将double 传递给采用int 参数的函数(具有已知原型),编译器将生成所需的转换代码。

    编译器是否对此类转换发出警告取决于编译器和您在命令行中请求的警告级别。

    对于转换int -&gt; double,通常(IEEE754 格式的 32 位(或 16 位)ints 和 64 位 doubles)是无损的,获得该转换的警告可能很难如果可能的话。

    对于double -&gt; int 转换,使用gcc 和clang,您需要使用-Wconversion 专门要求此类警告,否则它们会静默编译代码。

    【讨论】:

      【解决方案3】:

      Int 可以安全地自动向上转换为 double,因为没有数据丢失的风险。反过来是不正确的。要将 double 转换为 int,您必须显式转换它。

      【讨论】:

      • int foo = 42.3; 不需要演员表。 (C 中的强制转换经常是错误的)
      【解决方案4】:

      C 编译器使用 double 和 int 进行一些自动转换。 您还可以执行以下操作:

      int start = Data -> start_number;
      int localSum;
      
      for (start; start <= end; start++) {
         localSum += sqrt(start);
      }
      

      即使 localSum 是一个 int,它仍然可以工作,但它总是会删除任何超出点的内容。
      例如如果 sqrt() 的返回值为 1.365,它将被存储为一个简单的 1。

      【讨论】:

      • 我说的是“可以”而不是“应该”。它只是演示隐式转换的效果。
      猜你喜欢
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 2021-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多