为什么printf()在Python中给出一个奇怪的输出?

我试图在Linux的python命令行中使用C函数printf() 。 为了做到这一点,我导入了ctypes 。 我的问题是:如果我创build一个CDLL对象在CDLL中使用printf()函数,我得到一个非常奇怪的输出:

 >>> import ctypes >>> libc = ctypes.CDLL("libc.so.6") >>> for i in range(10): ... libc.printf("%d", i) ... 01 11 21 31 41 51 61 71 81 91 >>> 

但是,当我在一个函数中调用这个循环时,它按预期工作:

 >>> import ctypes >>> libc = ctypes.CDLL("libc.so.6") >>> def pr(): ... for i in range(10): ... libc.printf("%d", i) ... libc.printf("\n") ... >>> pr() 0123456789 >>> 

我无法猜测是什么原因导致这种行为
如果有问题,我在Linux上使用Python 2.7.6。

编辑:

Python版本/操作系统对此没有影响。 有关详细信息,请参阅下面的PM 2Ring的答案。 在Windows上,只需将libc = ctypes.CDLL("msvcrt.dll")的初始化更改为libc = ctypes.CDLL("msvcrt.dll") ,其中.dll是可选的。 另一种获得正确输出的方式比调用函数的方法是将printf()的返回值存储在一个variables中:

 >>> import ctypes >>> libc = ctypes.CDLL("libc.so.6") # "mscvrt.dll" on windows >>> for i in range(10): ... r = libc.printf("%d", i) ... 0123456789>>> 

我仍然更喜欢这个function,因为你可以更容易地添加结束的换行符。

每个数字末尾的那些额外的'1'是来自printf的返回值,它返回它打印的字符数。 交互式解释器中调用的函数的返回值会自动打印(除非是None )。

事实上,交互式解释器打印任何未分配的非Noneexpression式。 当然,它为这些expression式添加了一个换行符,这就解释了为什么第一个代码块中的输出是在不同的行上。

你的pr函数没有return语句,所以它返回None ,因此没有额外的东西被打印出来。

虽然PM 2Ring已经很好地回答了这个问题,但是我认为值得指出的是,printf的行为或者非常接近的东西可以作为一个python内置的,所以真的很奇怪你会使用C库版本,除非你用它来学习如何使用ctypes ,在这种情况下继续。

但是另一方面,当你没有使用足够的python来知道REPL是如何工作的时候想要使用ctypes是很奇怪的…冒着傲慢的风险,像有10年python经验的人,我从来没有实际上不得不使用ctypes呢。

在Python中有两个内置的string格式选项:

 print("%d" % (i,)) 

这是旧的风格,和printf非常相似

 print("{:d}".format(i)) 

这是python 3的新function,而且更强大一些。 有问题解决这个网站上的差异。 上述两行都将输出与libc.printf("%d\n", i) 。 也可以不使用换行符进行打印 。

“%”string格式的CPython实现实际上使用了sprintf。