首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

C语言 printf为啥酱紫

2012-09-02 
C语言 printf为什么酱紫?gcc4.4.3, 32位机#include stdio.hint main(int argn, char* argv[]){unsigned

C语言 printf为什么酱紫?
gcc4.4.3, 32位机

#include <stdio.h>

int main(int argn, char* argv[])
{
  unsigned int x = 0x3f800000;
  float y = *(float*)&x;
  printf("%f,%f,%d", y, x, sizeof(y));
  return 0;
}

运行结果:1.000000,0.000000,2514932

printf那句
换成printf("%f,%f,%d", x, y, sizeof(y));
运行结果:0.000000,0.000000,9707508

换成 printf("%f,%d,%f", y, sizeof(y), x);
运行结果:1.000000,4,0.000000

想不通。。。

[解决办法]
unsigned int x = 0x3f800000;
[解决办法]
1.000000,0.000000,-1080890052
0.000000,0.000000,-1076977156



[解决办法]
printf中的参数类型一定要匹配,不如结果不可预料,你可以试试如下的代码:

C/C++ code
#include <stdio.h>int main(int argc, char* argv[]){    unsigned int x = 0x3f800000;    float y = *(float*)&x;    printf("%f,%d,%d\n", y, x, sizeof(y));    printf("%d,%f,%d\n", x, y, sizeof(y));    printf("%f,%d,%d\n", y, sizeof(y), x);    return 0;}
[解决办法]
因为float转double了,所以你这里把整型作为float处理是不可以的,
[解决办法]
你仔细看看,主要是你x本身是整型,你却按照float/double去打印了。


探讨

为什么要匹配呢? printf实现时不是用变参实现的么?sizeof(int)和sizeof(float)是一样的,按我的理解说uint的0x3f800000应该按IEEE754的浮点数解释,结果为1.0才对。
引用:

printf中的参数类型一定要匹配,不如结果不可预料,你可以试试如下的代码:
C/C++ code

#include <stdio.h>

……

[解决办法]
正是因为参数可变,所以你类型不匹配的话,它的字节数会取错,导致后面的数据也打印不正确了。


探讨

为什么要匹配呢? printf实现时不是用变参实现的么?sizeof(int)和sizeof(float)是一样的,按我的理解说uint的0x3f800000应该按IEEE754的浮点数解释,结果为1.0才对。
引用:

printf中的参数类型一定要匹配,不如结果不可预料,你可以试试如下的代码:
C/C++ code

#include <stdio.h>

……

[解决办法]
探讨

printf中的参数类型一定要匹配,不如结果不可预料,你可以试试如下的代码:
C/C++ code

#include <stdio.h>

int main(int argc, char* argv[])
{
unsigned int x = 0x3f800000;

float y = *(float*)&amp;x;
printf("%f,%d,%d\n", y……

[解决办法]
试试这个
printf("%d,%f,%d",1,2,3,4);
[解决办法]
float转double
[解决办法]
探讨

正是因为参数可变,所以你类型不匹配的话,它的字节数会取错,导致后面的数据也打印不正确了。


引用:

为什么要匹配呢? printf实现时不是用变参实现的么?sizeof(int)和sizeof(float)是一样的,按我的理解说uint的0x3f800000应该按IEEE754的浮点数解释,结果为1.0才对。
引用:

printf中的参数……

[解决办法]
看下汇编就知道了,你的栈结构是4-4-8-4,函数的结构是4-8-8-4

printf("%f,%f,%d", y, x, sizeof(y), sizeof(y));\\偷懒的方法,骗一下编译器,呵呵呵
[解决办法]
LZ 例子中 int 类型参数不会自动转换到 double 类型。

像 printf、scanf 等含有可变参数的函数无法做完整的参数类型检查,或者说其 对从函数声明中已经明确的参数 都像强类型语言那样进行检查,而可变部分无能为力。目前见过的 lint 程序稍微能够做这种检查。对可变参数部分,编译器不查,也没能力检查,更别提类型转换了,它只是老实的把参数按照调用时的样子全数压栈(包括类型提升)。最经典的是一些 C 新手们调用 scanf 时变量前忘了加 & 而能够通过编译,还可以试试把参数写多点,或写少一两个,都能通过编译,但如果第一个参数不能是char* 的话,编译器就不干了。从这个角度讲,调用者与被调用者 能以这种方式正确的工作 才是真神奇。还是那句话,C认为程序员永远是对的。



类型提升:C传递参数时默认有两种类型提升,一是比 int 小的整型提升到 int,一是 float 提升到 double,原因不清楚,大概是历史原因吧(说性能原因很勉强);当然如果函数参数都是明确的话,编译器有权不这么做,但应该很少有编译器敢这么干吧。
[解决办法]

探讨

汇编代码如下:
Assembly code

.LC0: |
.string "%f,%f,%d" |
.text ……

[解决办法]
探讨

确实这样,奇怪的是sizeof(float)居然是 4, 存储时使用的是8个字节, 被编译器骗了,无语了。。。
引用:

引用:

汇编代码如下:
Assembly code

.LC0: |
.……