[英]float confusion- I'm confused how float specifier occurs
Consider the following code snippet 请考虑以下代码段
float a=12.2;
printf("%f %d",a,a); //output 12.200000 Garbage value
but 但
printf("%d %f",a,a);//Output Garbage value Garbage Value
my question is why in the second printf, both %d and %f gives garbage value. 我的问题是为什么在第二个printf中,%d和%f都给出了垃圾值。 I know it is because I have used %d first?..But can't find any proper explanation..
我知道这是因为我先用了%d?但是找不到任何正确的解释..
Using a wrong conversion specifier for a data type invokes undefined behavior . 对数据类型使用错误的转换说明符会调用未定义的行为 。 You may get anything, either expected or unexpected result.
您可能会得到任何预期或意外结果。
If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
如果转换规范无效,则行为未定义.282)如果任何参数不是相应转换规范的正确类型,则行为未定义。
Using %d
to print the value of a
( float
) results in undefined behavior of the program. 使用
%d
要打印的值a
( float
在程序的未定义的行为)的结果。
When you use the wrong specifier in printf
, things such the following can happen. 当您在
printf
使用错误的说明符时,可能会发生以下情况。
The caller does this: 来电者这样做:
float
arguments are converted to double
. float
参数将转换为double
。 printf("%d %f"), a, a)
, the caller first puts the last a
on the stack. printf("%d %f"), a, a)
,调用者首先将最后a
放在堆栈上。 The caller makes eight bytes of space by changing the stack pointer to 92, converts a
to double
, and writes eight bytes to the stack. a
转换为double
,并将8个字节写入堆栈,从而产生8个字节的空间。 a
, the caller changes the stack pointer to 84 and writes eight bytes to the stack. a
,调用者将堆栈指针更改为84并将八个字节写入堆栈。 "%d %f"
, the caller changes the stack pointer to 80 and writes a four-byte pointer to the stack. "%d %f"
,调用者将堆栈指针更改为80并将四字节指针写入堆栈。 Then printf
does this: 然后
printf
这样做:
printf
initializes a pointer to where the arguments start, 80. printf
初始化一个指向参数开始处的指针80。 printf
updates its argument pointer to point to 84. printf
其参数指针更新为指向84。 %d
, so printf
expects a four-byte integer, and it reads four bytes from 84. %d
,因此printf
需要一个四字节整数,它从84读取四个字节。 int
is four bytes, printf
updates its argument pointer to point to 88. int
是四个字节,因此printf
其参数指针更新为指向88。 double
, the four bytes from 84 to 87 do not make any sense as an int
, and printf
prints whatever int
value the bits happen to represent. double
的编码,因此从84到87的四个字节作为int
没有任何意义,而printf
打印该位恰好表示的int
值。 %f
, so printf
expects an eight-byte double
, and it reads eight bytes from 88. %f
,因此printf
需要一个8字节的double
,它从88开始读取8个字节。 double
and four bytes fro the start of the second double
, so they do not make any sense as a double
, and printf
prints whatever value the bits happen to represent. double
的末尾开始的四个字节和从第二个double
开始的四个字节,因此它们没有任何意义作为double
, printf
打印出该位碰巧代表的任何值。 This is not the way all C implementations work, but it is one thing that may happen when you use incorrect arguments with printf
. 这不是所有C实现的工作方式,但是当您对
printf
使用不正确的参数时,可能会发生这种情况。 The C standard makes the behavior undefined because it does not control how implementations work, so they might behave as described as above, but they might instead be passing some of the arguments in registers. C标准使行为不确定,因为它不控制实现的工作方式,因此它们的行为可能如上所述,但是它们可能会在寄存器中传递某些参数。 In the latter case, you would see different behaviors, such as
printf
printing garbage for %d
because nothing had set the corresponding integer register to an appropriate value but printf
printing the correct value for %f
because it looked for it in a floating-point register, and the caller did place the value of a
in a floating-point register. 在后一种情况下,您会看到不同的行为,例如
%d
printf
打印垃圾,因为没有将相应的整数寄存器设置为适当的值,但是printf
打印了%f
的正确值,因为它在浮点中查找它注册,主叫方没有地方的价值a
在浮点寄存器。
Because you can't know what will happen. 因为你不知道会发生什么。 If
sizeof(float) != sizeof(int)
, you will definitely get a garbage value twice in the second case, since printf
read either too many bytes or too few bytes from the first argument, so it will screw up when reading the next argument (assuming arguments were passed on stack). 如果
sizeof(float) != sizeof(int)
,你肯定会在第二种情况下得到两次垃圾值,因为printf
从第一个参数中读取太多字节或太少的字节,所以当读取下一个参数时它会搞砸参数(假设参数在堆栈上传递)。
Another issue that arises is that the argument passed is being converted to double
, which usually has a different size from int
, and then printf
tries to pick an int
from something that is double
. 出现的另一个问题是传递的参数被转换为
double
,它通常具有与int
不同的大小,然后printf
尝试从double
选择一个int
。 There is a size mismatch (see comments below). 尺寸不匹配(请参阅下面的评论)。
Either way, this invokes undefined behaviour, so you really can't "expect" anything meaningful to happen. 无论哪种方式,这都会调用未定义的行为,因此您实际上无法“期待”任何有意义的事情发生。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.