Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C `printf()`如何区分浮点参数和整型参数?_C_Floating Point_Printf - Fatal编程技术网

C `printf()`如何区分浮点参数和整型参数?

C `printf()`如何区分浮点参数和整型参数?,c,floating-point,printf,C,Floating Point,Printf,如果我有 printf("%f\n", 3); 我明白了 如果我有: printf("%f\n", 3.0); 我得到了同样的答案 但问题是,3和3.0应该是完全不同的 3.0应该类似于010000000100000000000000000000(但由于vararg函数中的隐式转换,因此具有双精度) 3应该类似于00000000000000000000000011 3在显示之前必须以某种方式转换为浮动 所以我的问题是,这是如何做到的?编译器不知怎么会作弊吗?如何在我自己的变量args函数中实

如果我有

printf("%f\n", 3);
我明白了

如果我有:

printf("%f\n", 3.0);
我得到了同样的答案

但问题是,3和3.0应该是完全不同的

3.0应该类似于
010000000100000000000000000000
(但由于vararg函数中的隐式转换,因此具有双精度)
3应该类似于
00000000000000000000000011

3在显示之前必须以某种方式转换为浮动


所以我的问题是,这是如何做到的?编译器不知怎么会作弊吗?如何在我自己的变量args函数中实现这一点?

如果源代码包含
printf(“%f\n”,3)结果输出为“3”,那么最有可能发生的情况如下:

  • 在程序中的其他地方有一个浮点3,例如
    x=3这样的赋值语句
    或另一个
    printf
    调用,例如
    printf(“%f\n”,3.0)
  • 为了使用该3,编译器将其加载到浮点寄存器中。它可能对
    printf
    之前的代码执行此操作,或者为
    printf
    之后的代码做准备
  • printf时(“%f\n”,3)%f
    转换说明符调用
    printf
    时,浮点3位于寄存器中,而
    double
    参数应该位于寄存器中
  • 因此,由于用于传递
    %f
    的参数的寄存器碰巧有一个浮点3,因此
    printf
    使用该值并产生一个结果“3”
换言之,您的程序在很大程度上是偶然发生的,而不是设计的。事实上,您确实错误地调用了
printf
,它只生成了“3”,因为不相关的因素恰好起作用。如果浮点寄存器中的值为5或−3.25,则printf将打印该值

printf
例程无法确定传递的值的类型。(好的编译器会在编译时检查类型,如果格式字符串是文本[而不是在运行时计算的内容]。但这是由编译器查看调用的源代码完成的,而不是由
printf
例程本身完成的。)

printf()
如何区分浮点参数和整型参数

printf()
依赖调用代码按其格式传递预期类型的对象


printf()
分析格式字符串,在本例中为
“%f\n”

“%f”
引导代码期望下一个参数是
双参数

如果传递了
浮点
,则它将转换为
双精度
,这是将参数转换为函数的
部分的一部分

调用代码传递了一个
float/double
printf()
将正确地以
double
的形式获取该数据并将其打印出来如果调用代码传递了其他类型,则结果是未定义行为(UB)。这是一个很好的解释

这是怎么做到的?编译器不知怎么会作弊吗

如何在我自己的变量args函数中实现这一点


OP看到的意外未定义行为不一定可以用用户代码重现。<代码>printf(“%f\n”,3)是未定义的行为。您使用了什么编译器?刚刚尝试了一下,输出0.00000。但正如所说,这是一种未定义的行为——这意味着编译器可以做它想做的事情,包括你所说的“作弊”,但对于编译器来说,为你“修复”你的坏代码是一种奇怪的(而且没有帮助的)行为。将编译器编写级别设置为高。有些编译器可以选择显式测试标准函数的格式说明符,也可以向使用相同格式说明符的检查中添加新函数。哪个编译器在哪个平台上为integer
3
生成
3.000000
?因为它是一个常量,所以编译器在编译时计算表达式的可能性很小(不太可能,但几乎是可能的)。尝试使用整数变量而不是文字,您会得到不同的结果。“我如何在自己的变量args函数中实现它?”:您真的不想这样做!相反,使用编译器的功能来验证格式说明符。正确答案出现在SO的注释中似乎是很常见的。谢谢我在Linux上使用GCC7。我没有用其他编译器尝试过。当我在XV6中重新实现printf的%f时,GCC似乎不再想作弊了:/
printf("%f\n", 3.0);