为什么printf中不会发生整数到双重转换 [英] Why do integer-to-double conversions do not happen in printf

查看:69
本文介绍了为什么printf中不会发生整数到双重转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我运行的代码如下:


#include< stdio.h>


int main()

{

printf("%f\ n",9/5);


返回0;

}


并且看到打印的值是-0.000000(gnu)或0.000000

(msvc6)。我期待2.000000。

接下来我试过这个:


#include< stdio.h>


int main()

{

int x = 27837;

/ ** 1 ** / double f = x;

printf("%f\ n",x);


返回0;

}


和现在打印的值是-1.98376(基本上是垃圾,gnu)和

0.000000(msvc6)。如果我注释掉我标有/ ** 1

** /的行,则返回打印-0.000000(gnu)或0.000000(msvc6)。

双重原因的声明是否与某些浮点链接

库会导致GNU的差异?


为什么不进行自动转换?

然后我尝试了以下两个:


#include< stdio.h>


int main()

{

int x = 27837;

double f = x;

printf("%f \\ \\ n",f);


返回0;

}


这样运作正常 - 我们得到27837.000000正如预期的那样。


这个:


#include< stdio.h>


int main()

{


int x = 27837;

void * v =& x;

double * f = v;

printf("%f\ n",* f);


返回0;

}


这又一次给了你tput,在我取消注释

" double f = x>之前,gnu与之前打印的垃圾具有不可思议的相似性。行。

发生了什么事?

- Arindam

解决方案

ar**************@gmail.com 写道:


我运行的代码如下:


#include< stdio.h>


int main()

{

printf("%f\ n",9/5);


返回0;

}


并且看到打印的值是-0.000000(gnu)或0.000000

(msvc6)。我期待着2.000000。



为什么?你试图用浮动格式打印一个int值(9/5的结果,即1)

。只有众神知道你会打印什么,

,因为标准说它是未定义的。结果是

取决于你的实现的数字表示的细节。


[似乎你可以说服gcc发现这个特殊情况使用

-Wall命令行选项。]


接下来我试过这个:


#include< stdio.h>


int main()

{

int x = 27837;

/ ** 1 ** / double f = x;

printf("%f\ n",x);


返回0;

}


和现在打印的值是-1.98376(基本上是垃圾,gnu)和

0.000000( MSVC6)。



您将打印另一个整数作为浮动值。更多未定义的

行为。正如医生所说,不要那样做。


如果我注释掉我用/ **标记的行

** /,然后返回打印-0.000000(gnu)或0.000000(msvc6)。



不在这里它不会。


双重原因的声明是否与某些链接相关联浮点

库会导致GNU的差异吗?


为什么不进行自动转换?



因为没有自动演员这样的东西,所以不需要

进行隐式转换。


然后我尝试了以下两个:


#include< stdio.h>


int main()

{

int x = 27837;

double f = x;

printf("%f\ n",f);


返回0;

}


这很好 - 我们按预期得到27837.000000。



/现在/你打印一个浮动作为一个浮动(严格来说,一个双倍的

作为一个双倍),它'定义明确,实现

实现它。


这个:


#include< stdio.h>


int main()

{

int x = 27837;

void * v =& x;

double * f = v;

printf("%f\\\
",* f);



和/ now /你试图从一个位置获取一个双倍值

保存整数值。你为什么期望这是远远的?
有意义吗?


返回0;

}


这又一次给出了输出,这与gnu有一个不可思议的相似之处就是它在我取消注释

之前打印的垃圾。 ; double f = x线。



可能是因为它获得相同的整数位然后尝试将
视为浮动位。
< blockquote class =post_quotes>
发生了什么事?



你正在做一些明显未定义的事情,并且有b $ b有幸获得明显的胡言乱语的结果,改变了/>
你的问题。


-

克里斯再次回到家里...... Dollin

永远不要问这个问题! Kosh大使/巴比伦5 /



ar ************** @ gmail.com 写道:


I正在运行如下代码:


#include< stdio.h>


int main()

{

printf("%f\ n",9/5);


返回0;

}


并且看到打印的值是-0.000000(gnu)或0.000000

(msvc6)。我期待着2.000000。



你为什么期待这个?


你告诉printf期望一个浮点数并传递给它/>
整数(除以两个整数产生整数结果)。你得到了什么

作为输出然后是未定义的。


接下来我尝试了这个:



[snip]


int x = 27837;

/ ** 1 ** / double f = x;

printf("%f\ n",x);



[snip]


你再次告诉printf()期望一个浮点数并传递一个

integaer。


,现在打印的值是-1.98376(基本上是垃圾,gnu)和

0.000000(msvc6) 。如果我注释掉我用/ ** 1

** /标记的行,那么它将返回打印-0.000000(gnu)或0.000000(msvc6)。


双重原因的声明是否与某些浮点链接

库会导致GNU的差异?



谁知道,谁在乎?你没有做任何明智的事情,所以

结果不需要有意义。


为什么不进行自动演员?



因为编译器无法知道需要演员表。


[snip]
< blockquote class =post_quotes>
int x = 27837;

double f = x;

printf("%f\\\
",f) ;



[snip]


这很好 - 我们按预期得到27837.000000。



当然......你把printf传递给你说过你会传递的数据类型

(好吧,那种 - 你说你会通过一个漂浮但是通过了一个双倍,我不能记得副手是否浮动会自动施放到

这里加倍 - 如果没有你的

平台上的浮动和双倍必须相同。


[snip]


int x = 27837;

void * v =& ;;



v包含27837的整数表示的地址。


double * f = v;



f包含整数表示形式的地址27837.


printf("%f\ n,* f);



您将27837的整数表示视为浮动

点数 - 为什么?


ar ********** **** @gmail.com 写道:


我运行的代码如下:


#include < stdio.h>


int main()

{

printf("%f\ n", 9/5);


返回0;

}


看到打印的值是 - 0.000000(gnu)或0.000000

(msvc6)。我期待2.000000。


接下来我试过这个:


#include< stdio.h>


int main()

{

int x = 27837;

/ ** 1 ** / double f = x;

printf("%f\ n",x);


返回0;

}


,现在打印的值是-1.98376(基本上是垃圾,gnu)和

0.000000(msvc6)。如果我注释掉我标有/ ** 1

** /的行,则返回打印-0.000000(gnu)或0.000000(msvc6)。


双重原因的声明是否与某些浮点链接

库会导致GNU的差异?


为什么不自动演员会发生什么?


然后我尝试了以下两个:


#include< stdio.h>


int main()

{

int x = 27837;

double f = x;

printf("%f\ n",f);


返回0;

}


这样工作正常 - 我们按预期得到27837.000000.


这个:


#include< stdio.h>


int main()

{


int x = 27837;

void * v = & x;

double * f = v;

printf("%f\ n",* f);


返回0;

}


和这一次a增益给出了输出,这与gnu有一个不可思议的相似之处,就是当我取消注释

" double f = x"行。


发生了什么事?


- Arindam



你必须明白,因为printf使用varargs(同样的问题

适用于使用varargs的任何函数)编译器无法为你做转换

。 printf唯一知道的是第一个参数是const

char *;所有其他参数的类型必须从格式

本身推断出来。通过指定%f,您已指定相应的

参数将为double,但您已通过各种不同的

类型。

(如果你指定Gnu C的-Wall选项它会指出

out)


-

Bill Medland


I was running code like:

#include <stdio.h>

int main()
{
printf("%f\n", 9/5);

return 0;
}

and saw that the value being printed was -0.000000 (gnu) or 0.000000
(msvc6). I was expecting 2.000000.
Next I tried this:

#include <stdio.h>

int main()
{
int x = 27837;
/**1**/ double f = x;
printf("%f\n", x);

return 0;
}

and the value now printed was -1.98376 (essentially garbage, gnu) and
0.000000 (msvc6). If I comment out the line I have marked with /** 1
**/, then it goes back to printing -0.000000 (gnu) or 0.000000 (msvc6).
Does the declaration of a double cause linking with some floating point
libraries which causes the difference on GNU?

Why does not an automatic cast happen?
I then tried the following two:

#include <stdio.h>

int main()
{
int x = 27837;
double f = x;
printf("%f\n", f);

return 0;
}

This works fine - we get 27837.000000 as expected.

And this:

#include <stdio.h>

int main()
{

int x = 27837;
void * v = &x;
double *f = v;
printf("%f\n", *f);

return 0;
}

and this once again gives output, which on gnu has an uncanny
similarity to the garbage it printed before just when I uncommented the
"double f = x" line.
What''s going on?
-- Arindam

解决方案

ar**************@gmail.com wrote:

I was running code like:

#include <stdio.h>

int main()
{
printf("%f\n", 9/5);

return 0;
}

and saw that the value being printed was -0.000000 (gnu) or 0.000000
(msvc6). I was expecting 2.000000.

Why? You''re trying to print an int value (the result of 9/5, ie, 1)
with a float format. Only the gods know what you''ll get printed,
since the standard says it''s undefined. The result is going to
depends on the details of your implementation''s numeric representations.

[It seems you can persuade gcc to spot this particular case using
the -Wall command-line option.]

Next I tried this:

#include <stdio.h>

int main()
{
int x = 27837;
/**1**/ double f = x;
printf("%f\n", x);

return 0;
}

and the value now printed was -1.98376 (essentially garbage, gnu) and
0.000000 (msvc6).

You''re printing a different integer as a floating value. More undefined
behaviour. As the doctor says, "Don''t do that.".

If I comment out the line I have marked with /** 1
**/, then it goes back to printing -0.000000 (gnu) or 0.000000 (msvc6).

Not here it doesn''t.

Does the declaration of a double cause linking with some floating point
libraries which causes the difference on GNU?

Why does not an automatic cast happen?

Because there''s no such thing as an "automatic cast", and no need here
for an implicit conversion.

I then tried the following two:

#include <stdio.h>

int main()
{
int x = 27837;
double f = x;
printf("%f\n", f);

return 0;
}

This works fine - we get 27837.000000 as expected.

/Now/ you''re printing a float as a float (strictly, a double
as a double), and it''s well-defined, and the implementation
implements it.

And this:

#include <stdio.h>

int main()
{
int x = 27837;
void * v = &x;
double *f = v;
printf("%f\n", *f);

And /now/ you''re trying to fetch a double value from a location
that holds integer values. Why do you expect this to be remotely
meaningful?

return 0;
}

and this once again gives output, which on gnu has an uncanny
similarity to the garbage it printed before just when I uncommented the
"double f = x" line.

Probably because it''s getting the same integer bits and then trying to
treat them as floating bits.

What''s going on?

You''re doing something that is conspicuously undefined, and have
had the good fortune to get obvious gibberish results, alterting
you to the problem.

--
Chris "back home once again ...." Dollin
"Never ask that question!" Ambassador Kosh, /Babylon 5/



ar**************@gmail.com wrote:

I was running code like:

#include <stdio.h>

int main()
{
printf("%f\n", 9/5);

return 0;
}

and saw that the value being printed was -0.000000 (gnu) or 0.000000
(msvc6). I was expecting 2.000000.

Why were you expecting that?

You told printf to expect a floating-point number and passed it an
integer (dividing two integers yields an integer result). What you got
as output then was undefined.

Next I tried this:

[snip]

int x = 27837;
/**1**/ double f = x;
printf("%f\n", x);

[snip]

You again told printf() to expect a floating-point number and passed an
integaer.

and the value now printed was -1.98376 (essentially garbage, gnu) and
0.000000 (msvc6). If I comment out the line I have marked with /** 1
**/, then it goes back to printing -0.000000 (gnu) or 0.000000 (msvc6).

Does the declaration of a double cause linking with some floating point
libraries which causes the difference on GNU?

Who knows, and who cares? You aren''t doing anything sensible, so the
results need not make sense.

Why does not an automatic cast happen?

Because the compiler has no way of knowing that a cast is needed.

[snip]

int x = 27837;
double f = x;
printf("%f\n", f);

[snip]

This works fine - we get 27837.000000 as expected.

Of course... You passed printf the type of data you said you''d pass
(well, sort of - you said you''d pass a float but passed a double, I
can''t remember off-hand whether float would be automatically cast to
double here - if not, float and double must be the same on your
platform).

[snip]

int x = 27837;
void * v = &;

v contains the address of the integer representation of 27837.

double *f = v;

f contains the address of the integer representation of 27837.

printf("%f\n", *f);

You treat the integer representation of 27837 as if it were a floating
point number - why?


ar**************@gmail.com wrote:

I was running code like:

#include <stdio.h>

int main()
{
printf("%f\n", 9/5);

return 0;
}

and saw that the value being printed was -0.000000 (gnu) or 0.000000
(msvc6). I was expecting 2.000000.
Next I tried this:

#include <stdio.h>

int main()
{
int x = 27837;
/**1**/ double f = x;
printf("%f\n", x);

return 0;
}

and the value now printed was -1.98376 (essentially garbage, gnu) and
0.000000 (msvc6). If I comment out the line I have marked with /** 1
**/, then it goes back to printing -0.000000 (gnu) or 0.000000 (msvc6).
Does the declaration of a double cause linking with some floating point
libraries which causes the difference on GNU?

Why does not an automatic cast happen?
I then tried the following two:

#include <stdio.h>

int main()
{
int x = 27837;
double f = x;
printf("%f\n", f);

return 0;
}

This works fine - we get 27837.000000 as expected.

And this:

#include <stdio.h>

int main()
{

int x = 27837;
void * v = &x;
double *f = v;
printf("%f\n", *f);

return 0;
}

and this once again gives output, which on gnu has an uncanny
similarity to the garbage it printed before just when I uncommented the
"double f = x" line.
What''s going on?
-- Arindam

You have to understand that because printf uses varargs (and the same issue
applies to any function using varargs) the compiler cannot do conversion
for you. The only thing printf knows is that the first argument is a const
char *; the type of all other arguments has to be inferred from the format
itself. By specifying %f you have specified that the corresponding
argument will be a double, but you have passed a variety of different
types.
(If you specify the -Wall option to the Gnu C it would have pointed that
out)

--
Bill Medland


这篇关于为什么printf中不会发生整数到双重转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆