首页 文章

在C中将int打印为float

提问于
浏览
7

我正在为Little Endian使用Visual Studio TC编译器 . 以下是这段代码:

void main()
{    
    float c = 1.0;
    int a = 0x3F800000;
    int *ptr = (int *)&c;
    printf("\n0x%X\n", *ptr);
    printf("\na = %f", a);
    printf("\nc = %f", c);
    return;    
}

输出是:

0x3F800000
a = 0.000000
c = 1.000000

浮点值1.0为0x3F800000,并在内存中存储为00 00 80 3F,适用于Little Endian . 将相同的值分配给int a . printf如何打印0.000000一段时间1.000000 for float c?我已经看到它在printf中使用%f打印时将所有整数值打印为0.000000 .

另外,由于printf是可变参数函数,它如何知道寄存器中传递的值是int还是float?

7 回答

  • 1

    施放变量

    printf("\na = %f", (float)a);
    printf("\nc = %f", (float)c);
    
  • 4

    在任何C实现中,都有关于如何将参数传递给函数的规则 . 这些规则可能会说某些类型的参数在某些寄存器中传递(例如,通用寄存器中的整数类型和单独的浮点寄存器中的浮点类型),大型参数(例如具有许多元素的结构)将在堆栈或指向结构副本的指针,依此类推 .

    在被调用函数内部,该函数在规则指定的位置查找它所期望的参数 . 当你在一个参数中传递一个整数到 printf 但是在格式字符串中传递它 %f 时,你在一个地方放一个整数,但是告诉 printf 寻找一个浮点数(已被提升为一个双精度数) . 如果C实现的规则指定整数参数在double参数的同一位置传递,则 printf 将找到整数的位,但它会将它们解释为double . 另一方面,如果C实现的规则为参数指定了不同的位置,那么整数的位不是 printf 查找double的位置 . 所以 printf 找到一些与你的整数无关的其他位 .

    此外,许多C实现具有32位 int 类型和64位 double 类型 . %f 说明符用于打印double,而不是float,并且在调用函数之前传递的float值将转换为double . 所以,即使 printf 找到整数的位,那里只有32位,但 printf 使用64位 . 所以打印的 double 由你传递的32位和32位其他位组成,这不是你的值打算打印 .

    这就是您使用 must 的格式说明符与您传递的参数匹配的原因 .

  • 6

    我遇到了类似的问题,最后我开发了一种方法来解决它,不确定这是否是你想要的 . 关键是:你应该传递一个浮点而不是一个整数 .

    #include <stdio.h>
    void printIntAsFloat();
    
    int main(void){
        printIntAsFloat();
    }
    
    void printIntAsFloat(){
        float c = 1.0;
        int a = 0x3F800000;
        int *ptr = (int *)&c;
        float *fp = (float*)((void*)&a); /*this is the key point*/
        printf("\n0x%X\n", *ptr);
        printf("\na = %f", a);
        printf("\nc = %f", c);
        printf("\nfp = %f", *fp);
        return; 
    }
    

    输出是这样的:

    0x3F800000
    
    a = 0.000000
    c = 1.000000
    fp = 1.000000
    

    OS:Fedora21 64位GCC版本:gcc版本4.9.2 20141101(Red Hat 4.9.2-1)(GCC)

  • 5
    int a= 0x3F800000;
    printf("\na = %f", *(float*)&a);//1.0
    
  • -1

    -Wall 所述: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘int’ . 这是未定义的行为,也会更详细地解释here .

    If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding coversion specification, the behavior is undefined.

    所以你在这里看到的是编译器构建器决定发生的事情,它可以是任何东西 .

  • 2

    我的通灵能力告诉我Adam Liss的评论是正确的答案: float 参数被提升为 double ,所以 printf() 函数期望发生这种情况:它期望堆栈上的64位值,但是得到32位加上垃圾数据恰好为零 .

    如果提高显示精度,显示应类似于 a = 0.00000000001 .

    这也意味着这应该工作:

    void main()
    {    
        double c = 1.0;
        long long a = 0x3FF0000000000000;
        long long *ptr = (long long *)&c;
        printf("\n0x%llX\n", *ptr);
        printf("\na = %f", a);
        printf("\nc = %f", c);
        return;    
    }
    
  • -1

    我已经用gcc编译了你的代码,生成的代码如下:

    movl    $0x3f800000, %eax
    movl    %eax, -4(%ebp)
    movl    $1065353216, -8(%ebp)
    leal    -4(%ebp), %eax
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    movl    (%eax), %eax
    movl    %eax, 4(%esp)
    movl    $LC1, (%esp)
    call    _printf
    movl    -8(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC2, (%esp)
    call    _printf
    flds    -4(%ebp)
    fstpl   4(%esp)
    movl    $LC3, (%esp)
    call    _printf
    

    这可能会给你一个提示,浮动参数不是从常规堆栈中获取的,而是来自浮点堆栈...我希望会有一些随机而不是0 ...

相关问题