printf格式f与Python中的d

时间:2013-12-17 22:13:04

标签: python c printf

我正在使用的一些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

2 个答案:

答案 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的参数的内存包含:

  1. 指向字符串文字"%.2lf
  2. 的指针
  3. 表示数字-145的字节。 (在x86-32或x86-64上,这是4个字节91 FF FF FF。)
  4. 一些垃圾数据。 (在上面的Python代码中,假设这是全零,但在C程序中它不一定是。)
  5. 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__或其他任何形式取决于它的格式。