C'deki printf () ve puts () arasındaki fark nedir?


176

Sana ile yazdırabilirsiniz biliyorum printf()ve puts(). Ayrıca printf()değişkenlerin enterpolasyonunu yapmanıza ve biçimlendirme yapmanıza olanak tanır.

puts()sadece ilkel bir versiyonu printf(). printf()String enterpolasyonu olmadan mümkün olan her şey için kullanılmalı mıdır?



47
Koymak yerine printf kullanma ile ilgili bir not: asla, asla printf(variable)bir dize yazdırmak için a. puts(variable)Veya tuşunu kullanın printf("%s', variable). Değişken biçimli bir dize kullanmanın güvenlik riski vardır: Değişken bir saldırgan tarafından yazılabilirse, biçim dizelerini kullanarak programa saldırabilirler.
Zan Lynx

Yanıtlar:


141

putsdaha basittir printfancak öncekinin otomatik olarak bir yeni satır eklediğini unutmayın. İstediğiniz bu değilse fputs, dizenizi stdout veya kullanmak için kullanabilirsiniz printf.


8
Ben de çıktı dizeye ek değişkenler eklemek için printf almak ek argümanlar bahsetmek önemli olduğunu düşünüyorum.
Erutan409

99

(Bu Zan Lynx tarafından yapılan bir yorumda belirtilmiştir, ancak bence bir cevaplamayı hak ediyor - kabul edilen cevabın bahsetmediği göz önüne alındığında).

Arasındaki temel fark puts(mystr);ve printf(mystr);ikincisi de bağımsız değişkeni olarak yorumlanır olmasıdır biçimlendirme dize . Sonuç dize herhangi bir kontrol karakterleri (içermiyorsa (katma yeni satır hariç) genellikle aynı olacaktır %) ama (eğer o güvenemez eğer mystryerine değişmez bir değişkendir) sen gerektiğini değil kullanabilirsiniz.

Bu nedenle, dinamik bir dizeyi tek bir argüman olarak geçirmek genellikle tehlikeli ve kavramsal olarak yanlıştırprintf :

  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

Aynısı fputsvs için de geçerlidir fprintf(ancak fputsyeni satırı eklemez).


Hangi şekilde kullanmak printf()daha az verimli olur? İşlem esnasında? Derleme zamanında mı?
franklin

10
@franklin çalışma zamanında, çünkü printfbiçim dizesini ayrıştırmak gerekiyor. Ancak, bunun normalde alakasız olması gerekir. Ayrıca, akıllı derleyici bu optimize etmek ve yerini alabilecek printfçağrı ileputs
leonbloy

33

Biçimlendirmenin yanı sıra, putsbaşarılı veya EOFbaşarısız olursa negatif olmayan bir tamsayı döndürür ; ise printf, yazdırılan karakter sayısını döndürür (sondaki boş değeri içermez).


16

Basit durumlarda, derleyici dönüştürür çağrıları printf()için çağrılarına puts().

Örneğin, bir sonraki göstereceğim montaj koduna aşağıdaki kod derlenecektir.

#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

Bu örnekte, GCC 4.7.2 sürümünü kullandım ve kaynağı ile derledim gcc -o hello hello.c.


9
Ve stdout'a yerleri koyan yeni çizgi ne olacak?
zubergu

1
printf("Hello world!\n");Gcc gerçekten bunu koyar çevirir olmalıdır . Eski bir mesaj olduğundan, kendim düzenleyeceğim.
Rafael Almeida

2
C kodunu derledikten sonra montaj kodunu nasıl okudunuz?
Koray Tugay

3
@KorayTugay: -save-tempsgcc seçeneği bunu yapıyor
schaiba

Bir ikili dosyayı sökmek için gdb gibi bir araç da kullanabilirsiniz.
Ivan Kaloyanov

10

Doğru, printfdaha güçlü bir versiyonu olarak düşünülebilir puts. printfolanağı sağlar biçimi gibi çıktı kullanılarak biçim belirteçleri için değişkenler %s, %d, %lf, vb ...


10

Deneyimlerime göre, biçim dizesi ne olursa olsun printf()daha fazla kod çeker puts().

Biçimlendirmeye ihtiyacım yoksa kullanmıyorum printf. Ancak, fwritehiç stdoutbir yeri daha hızlı çalışır puts.

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

Not: yorum başına '\ 0' bir tamsayı sabitidir. Doğru ifade sizeof(char)yorumlarda belirtildiği gibi olmalıdır .


2
"fwrite stdout koyar çok daha hızlı çalışır." - Sebebi ne olabilir?
Antony Hatchkins

6
@AntonyHatchkins Genellikle "çok" daha hızlı değildir. Bununla birlikte, puts (), dizenizde her seferinde strlen () çağrısı yapmak zorunda kalırken, boyut fwrite () ile biliniyorsa bu önlenebilir. Bu, performans farkına hemen hemen tek gerçek katkıda bulunuyor.
Wiz

8
Bu cevap yanlış. '\0'türü vardır int, bu nedenle çoğu sistemde bu yazdırılır Using fwrit. Eğer 1 daha az bayt yazdırmak istiyorsanız, sadece 1. kullanmak sizeof (char)Burada amaçlanan, 1. olması garanti ne muhtemeldir ki,
Bradley Garagan

8
int puts(const char *s);

puts () , stdout öğesine s ve sondaki yeni satırı yazar.

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

Printf () işlevi , sonraki bağımsız değişkenlerin çıktı için nasıl dönüştürüleceğini belirten bir biçim dizesinin kontrolü altında çıktıyı stdout'a yazar.

Bu fırsatı sizden belgeleri okumanızı istemek için kullanacağım.


5

printf () işlevi hem dizeleri hem de değişkenleri ekrana yazdırmak için kullanılırken, puts () işlevi yalnızca bir dizeyi yalnızca ekranınıza yazdırmanıza izin verir.


2

putsbasit bir seçimdir ve sonuna yeni bir satır ekler ve printfçıktıyı biçimlendirilmiş bir dizeden yazar.

İçin puts ve belgelerine bakın printf.

Ben sadece printfbu anahtarlama yönteminden daha tutarlı olduğu için kullanmanızı tavsiye ederim , yani hata ayıklama varsa tüm printfs aramak putsve daha az acı olur printf. Çoğu zaman çıktılarınızda da bir değişken çıktısını almak istersiniz, bu putsnedenle çoğunlukla örnek kodda kullanılır.


1

Karşılaştırma yaparken puts()ve printf()bellek tüketimi neredeyse aynı olsa bile, puts()karşılaştırıldığında daha fazla zaman alır printf().


Lütfen cevabınıza başkalarının ondan öğrenebilecekleri bir açıklama ekleyin - bu iddia için güvenilir kaynaklarınız var mı? Yoksa bu farkı açıklamak için bazı nedenler?
Nico Haase
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.