C语言中的printf()和puts()有什么区别?


176

我知道您可以使用printf()和打印puts()。我还可以看到,它printf()允许您插值变量并进行格式化。

是否puts()仅仅是一种原始的版本printf()。是否应将其用于printf()没有字符串插值的所有可能?



47
只是关于使用printf而不是puts的说明:永远不要做a printf(variable)打印字符串。使用puts(variable)printf("%s', variable)。使用变量格式字符串存在安全风险:如果变量可以由攻击者编写,则他们可以使用格式字符串来攻击程序。
Zan Lynx

Answers:


141

puts比简单,printf但请注意,前者会自动添加换行符。如果这不是您想要的,则可以fputs将字符串输出到stdout或使用printf


8
我认为也有必要提及printf用来将其他变量添加到输出字符串中的其他参数。
Erutan409

99

(Zan Lynx在评论中指出了这一点,但我认为值得一提-因为公认的答案没有提及它)。

puts(mystr);和之间的本质区别在于,printf(mystr);后者将参数解释为格式字符串。其结果将是往往是相同的(除了加入新行),如果字符串不包含任何控制字符(%),但如果你不能依赖于(如果mystr是一个变量,而不是文字),你应该 使用它。

因此,将动态字符串作为单个参数传递通常是危险的-从概念上讲是错误printf

  char * myMessage;
  // ... myMessage gets assigned at runtime, unpredictable content
  printf(myMessage);  // <--- WRONG! (what if myMessage contains a '%' char?) 
  puts(myMessage);    // ok
  printf("%s\n",myMessage); // ok, equivalent to the previous, perhaps less efficient

这同样适用于fputsVS fprintf(但fputs不会添加新行)。


使用哪种方式printf()效率较低?在运行时?在编译时?
富兰克林

10
@franklin在运行时,因为printf需要解析格式字符串。但是,这通常是无关紧要的。此外,一个聪明的编译器可以优化这一点,并更换printf与调用puts
leonbloy

33

除格式化外,puts如果成功或EOF失败,则返回非负整数;否则,返回非负整数。while printf返回打印的字符数(不包括结尾的null)。


16

在简单的情况下,编译器会将调用转换printf()puts()

例如,以下代码将编译为我接下来显示的汇编代码。

#include <stdio.h>
main() {
    printf("Hello world!");
    return 0;
}
push rbp
mov rbp,rsp
mov edi,str.Helloworld!
call dword imp.puts
mov eax,0x0
pop rbp
ret

在此示例中,我使用了GCC版本4.7.2,并使用编译了源代码gcc -o hello hello.c


9
那把新的行放在stdout中呢?
zubergu 2013年

1
printf("Hello world!\n");gcc确实应该将其转换为puts。由于这是旧消息,因此我将自己对其进行编辑。
拉斐尔·阿尔梅达

2
编译C代码后如何阅读汇编代码?
Koray Tugay

3
@KorayTugay:-save-tempsgcc 的选项可以做到这一点
schaiba

您也可以使用gdb之类的工具来分解二进制文件。
伊万·卡洛亚诺夫

10

是的,printf可以认为它是的更强大的版本putsprintf提供能力格式的变量用于使用输出格式说明如%s%d%lf等...


10

以我的经验,无论使用哪种格式的字符串printf(),都可以处理更多的代码puts()

如果不需要格式,则不要使用printf。然而,fwritestdout作品很多比快puts

static const char my_text[] = "Using fwrite.\n";
fwrite(my_text, 1, sizeof(my_text) - sizeof('\0'), stdout);

注意:每个注释中的'\ 0'是一个整数常量。正确的表达应sizeof(char)如注释所示。


2
“ fwrite到stdout的工作比puts快得多。” -可能是什么原因?
Antony Hatchkins 2013年

6
@AntonyHatchkins通常不会“快很多”。但是,puts()确实必须每次对字符串执行一次strlen()调用,而如果使用fwrite()知道大小,则可以避免。这几乎是造成性能差异的唯一真正因素。
Wiz

8
这个答案是不正确的。'\0'具有类型int,因此在大多数系统上都会打印Using fwrit。如果你想打印少1个字节,只使用1 sizeof (char),这很可能是你在这里有什么目的,是保证为1
布拉德利Garagan

8
int puts(const char *s);

puts()将字符串s和尾随换行符写入stdout。

int printf(const char *format, ...);

函数printf()在格式字符串的控制下将输出写入stdout,该格式字符串指定如何转换后续参数以输出。

我将借此机会请您阅读文档。



2

puts是简单的选择,并在末尾添加新行,并printf写入格式化字符串的输出。

查看文档putsprintf

我建议仅使用printf此方法,因为它比切换方法更一致,即,如果您正在使用debbugg,则搜索所有printfs的痛苦会小于putsprintf。多数情况下,您也希望在打印输出中输出变量,因此puts通常在示例代码中使用。


1

比较puts()和时printf(),即使它们的内存消耗几乎相同,puts()也比花费更多时间printf()


请在回答中添加一些解释,以便其他人可以从中学习-您是否有可靠的说法来源?还是某些原因可以解释这种差异?
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.