Cのprintf()とputs()の違いは何ですか?


176

私はあなたがして印刷することができます知っているprintf()puts()。また、printf()変数を補間してフォーマットを行うことができることもわかります。

puts()プリミティブバージョンにすぎませんprintf()printf()文字列補間なしで可能な限り使用する必要がありますか?



47
putsの代わりにprintfを使用する場合の注意事項:printf(variable)文字列を出力するためにa を実行することはありません。puts(variable)またはを使用しprintf("%s', variable)ます。変数のフォーマット文字列を使用すると、セキュリティ上のリスクがあります。攻撃者が変数を書き込める場合、フォーマット文字列を使用してプログラムを攻撃できます。
Zan Lynx

回答:


141

putsより簡単ですprintfが、前者は自動的に改行を追加することに注意してください。それがfputs目的に合わない場合は、文字列をstdoutまたはに使用できますprintf


8
出力された文字列に変数を追加するためにprintfが取る追加の引数に言及することも重要だと思います。
Erutan409 2015年

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()と効率が低下しますか?実行時に?コンパイル時?
フランクリン、2015年

10
printf書式文字列を解析する必要があるため、実行時に@franklin 。ただし、これは通常は無関係です。さらに、賢いコンパイラーはこれを最適化し、printfwithを次の呼び出しに置き換えることができます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
そして、標準出力に配置する新しい行はどうですか?
zubergu 2013

1
それはprintf("Hello world!\n");確かにそれをプットに変換するはずです。古いメッセージなので、自分で編集します。
Rafael Almeida

2
Cコードをコンパイルした後、アセンブリコードをどのように読みましたか?
Koray Tugay 2015年

3
@KorayTugay:-save-tempsgcc のオプションはそれを行います
schaiba '28

また、gdbのようなツールを使用してバイナリを逆アセンブルすることもできます。
Ivan Kaloyanov

10

右、printfのより強力なバージョンと考えることができましたputsprintfする機能を提供し、フォーマットなどの出力使用して書式指定用の変数%s%d%lf、等...


10

私の経験では、フォーマット文字列に関係なくprintf()、より多くのコードを取り込みputs()ます。

書式設定が必要ない場合は、使用しませんprintf。しかし、fwriteすることがstdoutたくさんよりも速く動作しますputs

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

注:コメントごとに、「\ 0」は整数定数です。正しい表現はsizeof(char)、コメントで示されているとおりでなければなりません。


2
「stdoutへのfwriteは、putよりもはるかに速く機能します。」-理由は何でしょうか?
アントニーハッチキンズ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に書き込みます。

この機会を利用して、ドキュメントを読むようにお願いします。


5

printf()関数は、文字列と変数の両方を画面に出力するために使用されますが、puts()関数は、文字列を画面にのみ出力することを許可します。


2

puts簡単な選択であり、最後に新しい行を追加printfし、フォーマットされた文字列から出力を書き込みます。

puts およびのドキュメントを参照してくださいprintf

printfこれは切り替え方法よりも一貫性があるため、使用することをお勧めします。つまり、デバッグしている場合puts、すべてのprintfを検索することは、およびよりも簡単printfです。ほとんどの場合、変数も印刷出力に出力したいので、putsコード例で主に使用されます。


1

とを比較するputs()printf()、メモリの消費量はほとんど同じですが、にputs()比べて時間がかかりますprintf()


他の人がそれから学ぶことができるように、あなたの回答にいくつかの説明を追加してください-その主張の信頼できる情報源はありますか?またはこの違いを説明するいくつかの理由?
ニコHaase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.