我正在使用的一些C
代码将int
设置为-145。根据格式,值将返回0.00
或-145
。采取以下
int a = -145;
printf("%.2lf", a); // returns 0.00
printf("%.2ld", a); // returns -145
第一个问题是第一行是如何返回0.00
的?第二个问题是如何在Python中返回0.00
?
在我尝试过的众多迭代中,有以下几种:
a = -145
"%0.2lf" % a # -145.00
"%0.2ld" % a # -145
"%0.2li" % a # -145
"%0.2f" % a # -145.00
答案 0 :(得分:4)
int a = -145;
printf("%.2lf", a); // returns 0.00
printf("%.2ld", a); // returns -145
两个函数调用都会调用未定义的行为。打印int
的正确转化说明符为d
而不是lf
(对于double
),而不是ld
(对于long
)。
答案 1 :(得分:0)
第二个问题是如何在Python中返回
0.00
?
如果你坚持:
import struct
def misinterpret_int_as_double(n):
int_bytes = struct.pack('i', n)
padding = b'\x00' * (struct.calcsize('d') - struct.calcsize('i'))
return struct.unpack('d', int_bytes + padding)[0]
>>> misinterpret_int_as_double(-145)
2.1219957193e-314
这基本上就是你的C代码在幕后所做的事情。 C不会对调用varargs函数的...
部分中传递的参数进行任何类型检查(在编译时或运行时)。发生的事情是存储printf
的参数的内存包含:
"%.2lf
。91 FF FF FF
。) printf
函数会看到lf
说明符,并且需要double
。因此,它将以下字节91 FF FF FF xx xx xx xx
(其中xx
=垃圾)解释为一个。对于大约1/4的垃圾可能值(包括00 00 00 00
),该数字足够小,可以舍入到零。
请注意,我假设了一堆东西:你有一个带有4字节int
和8字节double
的小端系统。该函数参数在内存中按升序传递。并且您的代码不会出现段错误。 YMMV在其他硬件/ OS /编译器组合上。这就是未定义行为的原因。
Python的工作方式不同,因为它是安全输入的。如果您将“错误”类型传递给str
的{{1}}运算符,则会通过调用魔术%
方法(或__float__
自动将操作数转换为正确的类型或__str__
或其他任何形式取决于它的格式。