【问题标题】:data type confusion in CC中的数据类型混淆
【发布时间】:2017-12-24 10:14:28
【问题描述】:

以下代码有效:

int main(void)
{  
   float f = get_float();
   int i = round(f*100);
   printf("%i\n", i); 
}

但是,如果这样编码会产生错误:

printf("%i\n", round(1.21*100));

输出显示round(1.21*100)float。那么,为什么

int i = round(f*100); 

还好吗?

【问题讨论】:

  • float 值分配给int 值时,会发生内部转换。 round() 给出一个双精度值,所以如果没有执行转换,它的值仍然是双精度值。在这种指定的情况下printf("%i\n", round(1.21*100)); 不执行转换,因此需要 '%f' 说明符来打印浮点值。

标签: c type-conversion


【解决方案1】:

这有点重复,但可能有助于更好地理解:

  1. round() 的原型如下:

    double round(double x);
    

    所以它返回double

  2. C 中有一个从doubleint隐式转换,所以写

    int i = round(f*100);
    

    round()的结果转换为int

  3. 如果您有一个需要 int 的函数,例如

    void printMyNumber(int number)
    {
        printf("%i\n", number);
    }
    

    你可以这样称呼它:

    printMyNumber(round(f*100));
    

    并且隐式转换按预期工作,因为编译器会看到这两种类型(round() 的返回类型和printMyNumber() 的预期参数类型)。

  4. 这不适用于printf() 的原因是printf() 的原型看起来像这样:

    printf(const char *format, ...);
    

    所以,除了第一个参数,参数的类型都是未知。因此,无论您传递什么,都无需任何转换即可传递(default argument promotions 除外)。当然,您可以使用 cast 来实现 显式转换

    printf("%i\n", (int) round(f*100)); // <- this is fine
    

【讨论】:

    【解决方案2】:

    当你这样做时

    int i = round(f*100); 
    

    转换double函数round的结果。转换后的结果存储在int 变量i 中,它可以与"%i" 格式一起使用,因为它需要int 参数。

    当您将rounddouble 结果直接作为参数传递给需要int 的格式时,您的格式和参数类型不匹配。这会导致未定义的行为

    在对printf 的调用中没有进行任何转换,并且由于printf 函数内的代码不知道参数的实际类型,因此无法进行任何转换。它只知道"%i" 的格式。对于可变参数函数,所有可能的类型信息都会丢失。

    【讨论】:

    • 好吧,“没有进行转换”,默认参数提升仍然完成。
    • @AnttiHaapala 好吧,因为该函数返回一个double 值,并且默认参数提升将是一个double,在这种特定情况下没有进行转换。
    【解决方案3】:

    这是因为自动类型转换的行为。在 printf 中,自动类型转换不起作用。当你说 %i 时,它只需要整数,它不能将 double 转换为整数然后打印。

    在赋值操作中,double先转换为整数,然后赋值给=运算符的左操作数。我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 2011-07-08
      相关资源
      最近更新 更多