2017-07-19 96 views
5

下面的代码工作:数据类型混淆用C

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

输出说round(1.21*100)float

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

然而,如果编码这种方式产生的错误。那么,为什么

int i = round(f*100); 

很好?

+3

当'float'值赋值给'int'值,内部发生转换。 'round()'给出一个double值,所以如果没有执行转换,它的值仍然是double。在这个指定的情况下'printf(“%i \ n”,round(1.21 * 100));'不执行转换,因此它需要'%f'说明符来打印float值。 – Sma

回答

15

当你

int i = round(f*100); 

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

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

没有转换是在调用作出printf,并没有转换可以进行自printf函数内部的代码不知道实际的参数类型。它只知道格式"%i"。所有可能的类型信息都会因可变参数函数而丢失。

+0

好吧,“没有进行转换”,默认参数促销仍然完成。 –

+0

@AnttiHaapala由于函数返回一个'double'值,而默认参数提升将会是一个'double',在这种特殊情况下不会进行转换。 –

5

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

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

4

这有点重复,但也许有助于为更好地理解:

  1. round()原型如下:

    double round(double x); 
    

    所以它返回double

  2. 有一个隐式转换double在C int,所以写

    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)。当然,你可以使用一个以达到显式转换代替:

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