Apa perbedaan antara printf () dan puts () di C?

176

Saya tahu Anda dapat mencetak dengan printf()dan puts(). Saya juga bisa melihat yang printf()memungkinkan Anda untuk menginterpolasi variabel dan melakukan pemformatan.

Ini puts()hanyalah versi primitif dari printf(). Haruskah digunakan untuk setiap kemungkinan printf()tanpa interpolasi string?

alex
sumber
47
Hanya catatan tentang menggunakan printf daripada menempatkan: tidak pernah, pernah melakukan printf(variable)untuk mencetak string. Gunakan puts(variable)atau printf("%s', variable). Ada risiko keamanan dalam menggunakan string format variabel: jika variabel dapat ditulis oleh penyerang mereka dapat menyerang program dengan menggunakan string format.
Zan Lynx

Jawaban:

141

putslebih sederhana daripada printftetapi perlu diketahui bahwa yang pertama secara otomatis menambahkan baris baru. Jika bukan itu yang Anda inginkan, Anda dapat fputsmenggunakan string atau stdout Anda printf.

Michael Kristofik
sumber
8
Saya pikir ini juga penting untuk menyebutkan argumen tambahan printf untuk menambahkan variabel tambahan ke dalam string yang dihasilkan.
Erutan409
99

(Ini ditunjukkan dalam komentar oleh Zan Lynx, tapi saya pikir ini layak mendapat jawaban - karena jawaban yang diterima tidak menyebutkannya).

Perbedaan mendasar antara puts(mystr);dan printf(mystr);adalah bahwa dalam argumen terakhir ditafsirkan sebagai string pemformatan . Hasilnya akan sering sama (kecuali untuk baris baru yang ditambahkan) jika string tidak mengandung karakter kontrol apa pun ( %) tetapi jika Anda tidak dapat mengandalkan itu (jika mystrmerupakan variabel, bukan literal) Anda tidak boleh menggunakannya.

Jadi, umumnya berbahaya - dan salah secara konsepsi - melewatkan string dinamis sebagai argumen tunggal 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

Hal yang sama berlaku untuk fputsvs fprintf(tetapi fputstidak menambahkan baris baru).

leonbloy
sumber
Dengan cara apa penggunaannya printf()menjadi kurang efisien? Saat berjalan? Pada waktu kompilasi?
franklin
10
@ Franklin saat runtime, karena printfperlu mengurai format string. Namun, ini seharusnya tidak relevan. Lebih lanjut, kompiler yang cerdik dapat mengoptimalkan ini, dan mengganti printfpanggilan denganputs
leonbloy
33

Selain memformat, putsmengembalikan bilangan bulat non-negatif jika berhasil atau EOFjika tidak berhasil; sementara printfmengembalikan jumlah karakter yang dicetak (tidak termasuk nol tertinggal).

echristopherson
sumber
16

Dalam kasus sederhana, kompiler mengubah panggilan menjadi printf()ke puts().

Misalnya, kode berikut akan dikompilasi ke kode perakitan yang saya tunjukkan selanjutnya.

#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

Dalam contoh ini, saya menggunakan GCC versi 4.7.2 dan mengkompilasi sumbernya gcc -o hello hello.c.

Hannu Balk
sumber
9
Dan bagaimana dengan baris baru yang menempatkan tempat di stdout?
zubergu
1
Seharusnya printf("Hello world!\n");gcc memang menerjemahkannya untuk menempatkan. Karena ini adalah pesan lama, saya akan mengeditnya sendiri.
Rafael Almeida
2
Bagaimana Anda membaca kode rakitan setelah mengkompilasi kode C?
Koray Tugay
3
@ KorayTugay: -save-tempsopsi untuk gcc melakukan itu
schaiba
Anda juga bisa menggunakan alat seperti gdb untuk membongkar sebuah biner.
Ivan Kaloyanov
10

Benar, printfbisa dianggap sebagai versi yang lebih kuat puts. printfmenyediakan kemampuan untuk format yang variabel untuk output menggunakan format specifiers seperti %s, %d, %lf, dll ...

Justin Ethier
sumber
10

Dalam pengalaman saya, printf()mengangkut lebih banyak kode daripada puts()terlepas dari format string.

Jika saya tidak membutuhkan format, saya tidak menggunakan printf. Namun, fwriteuntuk stdoutbekerja jauh lebih cepat daripada puts.

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

Catatan: per komentar, '\ 0' adalah konstanta integer. Ekspresi yang benar harus sizeof(char)seperti yang ditunjukkan oleh komentar.

Thomas Matthews
sumber
2
"fwrite to stdout bekerja jauh lebih cepat daripada menempatkan." - Apa yang mungkin menjadi alasannya?
Antony Hatchkins
6
@AntonyHatchkins Biasanya tidak "banyak" lebih cepat. menempatkan (), bagaimanapun, harus melakukan panggilan strlen () setiap kali pada string Anda sedangkan jika ukurannya diketahui dengan fwrite () itu dapat dihindari. Itu adalah satu-satunya kontributor nyata untuk perbedaan kinerja.
Wiz
8
Jawaban ini salah. '\0'memiliki tipe int, jadi pada kebanyakan sistem ini akan mencetak Using fwrit. Jika Anda ingin mencetak 1 byte lebih sedikit, gunakan saja 1. sizeof (char), yang kemungkinan Anda maksudkan di sini, dijamin menjadi 1.
Bradley Garagan
8
int puts(const char *s);

puts () menulis string s dan baris baru yang tertinggal ke stdout.

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

Fungsi printf () menulis output ke stdout, di bawah kendali string format yang menentukan bagaimana argumen selanjutnya dikonversi untuk output.

Saya akan menggunakan kesempatan ini untuk meminta Anda membaca dokumentasi.

Koray Tugay
sumber
5

fungsi printf () digunakan untuk mencetak string dan variabel ke layar sementara fungsi put () hanya memungkinkan Anda untuk mencetak string hanya ke layar Anda.

Wesley Nyandika
sumber
2

putsadalah pilihan sederhana dan menambahkan baris baru pada akhirnya dan printfmenulis output dari string yang diformat.

Lihat dokumentasi untuk puts dan untuk printf.

Saya akan merekomendasikan untuk menggunakan hanya printfkarena ini lebih konsisten daripada metode switching, yaitu jika Anda debbugging itu kurang menyakitkan untuk mencari semua printfs daripada putsdan printf. Sering kali Anda ingin menampilkan variabel dalam cetakan Anda juga, jadi putssebagian besar digunakan dalam kode contoh.

Johan Engblom
sumber
1

Saat membandingkan puts()dan printf(), meskipun konsumsi memori mereka hampir sama, puts()membutuhkan waktu lebih lama dibandingkan printf().

sampai
sumber
Harap tambahkan beberapa penjelasan pada jawaban Anda sehingga orang lain dapat belajar darinya - apakah Anda memiliki sumber tepercaya untuk klaim itu? Atau beberapa alasan untuk menjelaskan perbedaan ini?
Nico Haase