为什么它的结果会是0??

thankall 2006-03-09 10:28:56
#include <stdio.h>

void main()

{

int x=5,y=1;

printf("\n%d",x>y?1:1.5);

}
...全文
487 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
caiyujie87 2006-03-21
  • 打赏
  • 举报
回复
mark
tzk 2006-03-12
  • 打赏
  • 举报
回复
ddddh(叶君临),强!
学习
zzw820626 2006-03-12
  • 打赏
  • 举报
回复
用了"%d就表示输出一个整形,但是1.5是浮点数
sankt 2006-03-12
  • 打赏
  • 举报
回复
学习
mp6 2006-03-12
  • 打赏
  • 举报
回复
“浮点形1在c++32位机中表示为00011111 10000000 00000000 00000000”
这个是错的,应该是:00111111 10000000 00000000 00000000
wangmuqq88 2006-03-12
  • 打赏
  • 举报
回复
欢迎大家加群(C/C++)20641933欢迎大家共同学习交流
lishijin8096 2006-03-09
  • 打赏
  • 举报
回复
printf("%d\n",int(x>y?1:1.5));
wqtl_357 2006-03-09
  • 打赏
  • 举报
回复
应该是printf中可变参数中表达式不是按常规方式运行。
除了把1.5改为一个整形,以下两种方式也可以。

/* <1> */
#include <stdio.h>

void main()
{
int x=5,y=1;
printf("%f\n", x>y ? 1 : 1.5);
}

/* <2> */
#include <stdio.h>

void main()
{
int x=5, y=1;
int t = (x>y) ? 1 : 1.5;
printf("%d\n", t);
}
thankall 2006-03-09
  • 打赏
  • 举报
回复
我只知道把那个1.5换成一个整型的数就可以了,但不知道为什么
wumingchenchao 2006-03-09
  • 打赏
  • 举报
回复
这个问题我终于搞明白了。
thankall 2006-03-09
  • 打赏
  • 举报
回复
看得不是很明白,能不能给具体地讲一个你的测试程序??
ddddh 2006-03-09
  • 打赏
  • 举报
回复
这个问题不错。我刚才研究了一下,发现有点意思:)

printf ("%d", x > y ? 1 : 1.5);

最后一个表达式的类型是double,一般32位系统上,double的大小是8个字节。而%d是用来处理int型的,int型是4个字节,完全有可能这个double的低32位是0,所以输出为0不足为奇。验证一下:

int main()
{
  double d = 1;
  char *c = (char *)&d;
  int i;
  for (i = 0; i < sizeof(d); ++ i)
    printf ("%d - %d\n", i, (int)*c ++);
  return 0;
}
我们得到的输出是:
0 - 0
1 - 0
2 - 0
3 - 0
4 - 0
5 - 0
6 - -16
7 - 63
果然,低32位(4个字节)都是0。所以这个结论不难解释。


那么我们再试试看,如果类型是float呢?我们知道float的大小也是4个字节,和int一样大。那么按照常理推之,printf("%d", float)如果float不是0,应该能输出一个不是0的值。

int main()
{
  printf ("%d", (float)1);
  return 0;
}

编译,输出,结果还是0,而我们知道1的浮点表示并不是全部为0的,此时我也觉得有些奇怪了。

这时候只能求助于汇编代码了:

void foo(float f)
{
  printf ("%d", f);
}

void bar(double d)
{
  printf ("%d", d);
}

反汇编得到:
subl $24, %esp
flds 8(%ebp)
fstpl 4(%esp)
movl $LC0, (%esp)
call _printf

subl $24, %esp
fldl 8(%ebp)
fstpl 4(%esp)
movl $LC0, (%esp)
call _printf

关键在于fldl/flds和fstpl两条指令。
函数foo里面参数是float,所以首先使用flds,从堆栈上把这个float加载到处理器的浮点寄存器堆栈中,这个堆栈是80位精度的。然后再用fstpl,从浮点寄存器堆栈中,把这个80位精度的值,弹出来,作为一个double(64位)压入堆栈。也就是说,就算我们传入的参数是一个float,当它被压入堆栈的时候,它已经变成了一个double类型。

在bar()里面,我们看到,除了在加载的时候使用了fldl(用以加载double,flds用以加载float),其他部分都是一样的。

所以我们看到对于printf(const char *, ...)这样的函数,后面带...的,如果你用的参数是float,实际上是当成double传进去的,也就是说,8个字节。




楼上的说%d只认最后8位,是不对的:-)
thankall 2006-03-09
  • 打赏
  • 举报
回复
浮点形1在c++32位机中表示为00011111 10000000 00000000 00000000

这个是为什么????
lovexpshl 2006-03-09
  • 打赏
  • 举报
回复
整形1在c++32位机中表示为00000000 00000000 00000000 00000001
浮点形1在c++32位机中表示为00011111 10000000 00000000 00000000

%d格式输出时计算机只认最后8位即00000000所以输出为0
popoxx 2006-03-09
  • 打赏
  • 举报
回复
用了"%d就表示输出一个整形,但是1.5是浮点数

69,379

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧