2016-04-30 25 views
8

Đây là chương trình C của tôi sử dụng puts():sự khác biệt giữa puts và printf trong C biên dịch thành ngôn ngữ hội là gì

#include <stdio.h> 
int main(void){ 
puts("testing"); 
} 

Sau khi sử dụng gcc -S -o sample.s sample.c để biên dịch nó thành hội, đây là những gì tôi nhận:

 .file "sample.c" 
     .section  .rodata 
.LC0: 
     .string "testing" 
     .text 
.globl main 
     .type main, @function 
main: 
     pushl %ebp 
     movl %esp, %ebp 
     andl $-16, %esp 
     subl $16, %esp 
     movl $.LC0, (%esp) 
     call puts 
     leave 
     ret 
     .size main, .-main 
     .ident "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)" 
     .section  .note.GNU-stack,"",@progbits 

tôi đã làm theo cách tương tự, lần này tôi đã sử dụng printf() thay vì puts và đây là những gì tôi nhận:

.file "sample.c" 
     .section  .rodata 
.LC0: 
     .string "testing" 
     .text 
.globl main 
     .type main, @function 
main: 
     pushl %ebp 
     movl %esp, %ebp 
     andl $-16, %esp 
     subl $16, %esp 
     movl $.LC0, %eax  //this is the difference 
     movl %eax, (%esp) 
     call printf 
     leave 
     ret 
     .size main, .-main 
     .ident "GCC: (GNU) 4.4.5 20110214 (Red Hat 4.4.5-6)" 
     .section  .note.GNU-stack,"",@progbits 

Dưới đây là những gì tôi không hiểu, các printf() chức năng mov $.LC0-%eax, sau đó mov %eax-(%esp) trong khi puts() chức năng mov %.LC0 trực tiếp đến (%esp). Tôi không biết tại sao lại như thế.

+6

Có lẽ vì 'printf' là một chức năng varargs, và họ được gọi cách khác nhau từ chức năng mà có một số cố định của các đối số. – Barmar

+1

Thú vị đủ, sử dụng clang trên os x, cả hai chương trình biên dịch vào cùng một hội đồng. – Leandros

+0

Ngoài ra tại sao GCC biên dịch mã phụ thuộc vào vị trí trên linux? – Leandros

Trả lời

4

Sự khác biệt lớn giữa hai hàm, ở cấp độ lắp ráp, là hàm puts() sẽ chỉ lấy một đối số (một con trỏ đến chuỗi hiển thị) và hàm printf() sẽ lấy một đối số (con trỏ đến định dạng chuỗi) và, sau đó, một số lượng đối số tùy ý trong ngăn xếp (printf() là hàm variadic).

Lưu ý rằng, hoàn toàn không có kiểm tra số đối số, nó chỉ phụ thuộc vào số lượng thời gian mà ký tự % gặp phải trong chuỗi định dạng. Ví dụ, tính đặc hiệu này được sử dụng trong phương pháp khai thác lỗi định dạng chuỗi định dạng để tương tác khám phá nội dung của chồng của một quá trình.

Vì vậy, về cơ bản, sự khác biệt là puts() chỉ có một đối số và printf() là hàm variadic.

Nếu bạn muốn hiểu rõ hơn về sự khác biệt này, hãy cố gắng biên dịch:

#include <stdio.h> 

int main(void) { 
    printf("testing %d", 10); 
} 
+1

Cũng đáng nói rằng 'puts' nối một' \ n' hoàn toàn, không giống 'fputs'.Xem thêm [hai trường hợp mà trình biên dịch tối ưu hóa printf để đặt, và hai trường hợp mà nó không] (https://godbolt.org/g/w2d2fI). Và http://stackoverflow.com/questions/36343733/o2-optimizes-printfs-n-str-to-putsstr. –

Các vấn đề liên quan