2014-10-23 15 views
9

kod sadece 2 satır:Bazıları bu davranışı açıklayabilir mi? Lütfen bu pasajı açıklamak

#include <stdio.h> 

int puts(const char *str) { 
    fputs("Hello world!\n", stdout); 
} 

int main() { 
    printf("Goodbye\n"); 
} 

Çıktı: Hello world! dönüş 13

+2

C90 ve yoksayılmış tanılama? – Deduplicator

+0

GCC, çağrıların ve printf basit dizinin + newline çağrısının yerini alır. – BLUEPIXY

+2

Masum görünümlü kütüphane işlevlerini kendi kodunuzla değiştirerek neler yapabileceğinizi gösterir. Her şeyden önce, orada evinizi arayabilir veya bu, bankacılık yazılımı ise yüzde kesirleri aktarabilir veya eğer root olarak çalışıyorsa/etc/passwd içine bir satır ekleyebilirsiniz. –

cevap

6

Benim tahminim gerek yoktur çünkü derleyici, puts() bir çağrı içine printf() çağrısına değiştiğine dikkat olurdu biçimlendirme nedeniyle printf() için. Ayrıca dize, puts()'a uyan bir satırsonuyla sonlandırılır. Derleyici, bir kütüphane işlevinin korkunç yükünü göremedi, bu yüzden "kandırdı".

10

Derleyici özeldir. Bu davranışı GCC ile alırsınız. İşte bazı detaylar.

  • yana #include <stdio.h> (eğer barındırılan bir ortamda, çünkü aslında) puts C99 standardının olması ve bunun undefined behavior

  • GCC derleyicisi için bazı printf dönüştürmek için bazı optimizasyonlar sahiptir yeniden tanımlanması bir dizi daha hızlıputs. Eğer <stdio.h> dahil ettik, bu durum yasal (ve C99 standart printf bu durumda ne yapması gerektiğini tanımlar; GCC bir ara adım olarak __builtin_printf aracılığıyla gider) Eğer -ffreestanding ile derlemek Eğer bunu gözlemlemek olmayacak

.

Sorunuz this one; this answer da ilgilidir.

+0

Muhtemelen bu konuda değil, düz UB. Ve bu yasaldır çünkü barındırılan bir ortam için derler, içerdiği önemli değildir. – Deduplicator

+0

Bu, yasaldır çünkü uyumlu bir program için gözlemlenebilir davranışını değiştirmez. – Deduplicator

7

Programı gcc x.c -S -o- ile derledim. Aynı anlambilgisi gibi, beni çok gerçekten printf çağrı GCC puts değiştirilir

[...] 
main: 
.LFB1: 
     .cfi_startproc 
     pushl %ebp 
     .cfi_def_cfa_offset 8 
     .cfi_offset 5, -8 
     movl %esp, %ebp 
     .cfi_def_cfa_register 5 
     andl $-16, %esp 
     subl $16, %esp 
     movl $.LC1, (%esp) 
     call puts 
     leave 
     .cfi_restore 5 
     .cfi_def_cfa 4, 4 
     ret 
     .cfi_endproc 
.LFE1: 

verdi.

İlgili konular