為什麼C語言的Hello,world都是用printf輸出而不是puts?
幾乎所有C語言教材的hello,world都是用printf輸出的。
我覺得printf是「格式化輸出」,僅僅輸出一個字元串是大材小用了,而且還要手動加"
"。相比之下,puts含義明確(輸出一行文字),不用加"
"就自動換行,是輸出一行字最簡單的方式,為什麼不用它寫hello,world呢?有些人寫代碼總是printf("%s
",s)而不是直接puts(s),我也不太理解。
用一行類似於printf("Hello World")的語句來開始學習一門編程語言。事實上不止是C語言,市面上幾乎所有語言的所有語言入門教程都是這麼乾的。我的理解是,向 丹尼斯·李奇 先生致敬,他當年為地球打開新世界的《The C Program Language》一書就是這麼乾的。至於他為什麼這麼干,我認為別的回答更有道理
至於為什麼大家不愛用puts(),恰恰是因為它的功能專註而單一,課本里並沒有側重於它,老師授課也沒有側重於它,考試也沒有側重於它。
真相往往就是這麼簡單。 8 main:
9 .LFB0:
10 .cfi_startproc
11 pushl %ebp
12 .cfi_def_cfa_offset 8
13 .cfi_offset 5, -8
14 movl %esp, %ebp
15 .cfi_def_cfa_register 5
16 andl $-16, %esp
17 subl $16, %esp
18 movl $.LC0, (%esp)
19 call puts #編譯器將printf優化為puts
20 leave
21 .cfi_restore 5
22 .cfi_def_cfa 4, 4
23 ret
24 .cfi_endproc
代碼可讀性比什麼都重要。用printf有以下幾個理由:
1. print本身有列印的意思,新手和其他語言使用者能很快理解這句話的意思。
2. printf傳入的參數就是實際的列印結果,你不需要再用人腦去模擬puts增加換行的過程。
3. 減少相似功能函數的混用。舉個簡單的例子,新手學c++的時候會cin一行之後用gets,然後gets得到的是個換行符。。同樣道理,混用puts和printf也會經常多個換行少個換行,最好統一。然而puts能替代printf么?顯然不行,那麼答案自然只有統一用printf。
最後我想說,在計算機如此發展,編譯器如此發達的今天,請不要太在意「非數量級」上的性能差異。程序的可讀性真的真的比什麼都重要。殺雞就用牛刀,怎麼了?
沒有人說printf和fprintf是非安全函數嗎?程序員們小心點,這個函數經常是黑客的攻擊目標,尤其是列印的內容裡面有用戶輸入的信息的時候,分分鐘被黑客打破
如果只學一種輸出方法的話 printf比puts能應用的場合更多事實上調用puts的cost比調用printf小 但printf支持formatted string,支持不自動換行,所以適應性更廣。能用puts還用printf可能一是為了保持代碼的一致性 二是因為常年一致的用printf忘了puts的存在…作為入門教材選用printf就是給讀者一種能輸出大多數東西的方法 因為顯然光知道printf可以 但光知道puts不行
有些人寫代碼總是printf("%s
",s)而不是直接puts(s),我也不太理解。
printf("%s
",s)確實是很蠢的一種寫法,【根據後來的個別回答,某些實現會把printf("%s
",s)自動優化為puts(s)。這說明連編譯器都對printf("%s
",s)看不下去了】
")(譚浩強就一向如此),而不是寫成putchar("
")。
======================================
幾乎所有C語言教材的hello,world都是用printf輸出的。
我覺得printf是「格式化輸出」,僅僅輸出一個字元串是大材小用了,而且還要手動加"
"。相比之下,puts含義明確(輸出一行文字),不用加"
"就自動換行,是輸出一行字最簡單的方式,為什麼不用它寫hello,world呢?
你說得有一定道理。
問題在於你看的教材要講什麼以及講沒講。就KR而言,在講hello,world時還介紹了,以及
printf("hello,");
printf("world");
printf("
");
這種等價寫法。
這兩個知識是用puts()不勝任的。比如,puts()本身如你所說,「不用加""就自動換行」(實際是遇到 輸出
),這就很難引入對
的介紹,因為不需要。如果硬要引入(比如在字元串中間加
)則顯得很不自然,而且很難解釋 轉成
的問題。用用puts()的另一個問題是沒法把"hello,world"分成幾段逐次輸出。而把"hello,world"分成幾段逐次輸出對於學習者深入理解「程序」這個概念、學習美化C程序格式以及領略C語言靈活的特點的是很有意義的。
So,如果你的教材介紹了相關的知識,那麼使用printf()講hello,world無可非議;如果沒介紹相關知識,那就是東施效顰,還不如用puts()。
=============回答一下 @an Aaron 的疑問:首先,printf("%s",s)從思想上來說繞了一個彎子,它的意思是把一個字元串插入到%s處輸出,puts(s)則直截了當,就是輸出字元串;其次,前者要用兩個實參,後者只用一個。寫程序的人都知道,寫得越多出錯的可能性越大;第三,代碼哪個簡潔是一目了然的;第四,printf()與puts()函數的實現方法不同,前者要複雜得多,至少要多一個對格式字元串分析的步驟。所以從執行效率上來看,顯然也是後者為優。調用時空間方面後者也同樣為優。============================至於 @pansz 所說的「
因為工程上經常需要用宏重定義printf,來實現將輸出定向到其它目標的目的。如果使用多個不同的輸出函數就會顯得很麻煩。"
我不能確信我是否確實理解了他所說的是怎樣一種情況。據我所知,puts()同樣能完成重新定向的功能。
我希望@pansz 能進一步補充說明一下那樣寫的前提條件。格式化輸出用的太頻煩了,習慣了,此外性能差別相當小
一開始別在意這種問題 編譯器會轉成puts putc 這種
puts太弱了,只能輸出一個字元串,其他很多語言都有字元串相加,這樣基本的輸出就變得強大了許多,
KR的書的第二個例子是攝氏溫度與華氏溫度的轉換,所以啊
因為puts必然可以被printf取代,但printf可不是總能被puts取代的(廢話)既然沒必要我為什麼要增加自己的學習負擔?我只要學會printf就夠了,根本不需要去學puts(我還是剛剛Google了一下,才確認了puts會在結尾自動加
)
C語言第一行代碼就是printf。大家都有先入為主的概念。
看一看各大語言的Hello World怎麼寫……
/* C */
#include &
int main(void) {
printf("Hello, world!");
return 0;
}
REM BASIC
PRINT "HELLO, WORLD!"
print("Hello, world!") # Python
print "Hello, world!" # Perl
Form1.Print "Hello, world!" "Visual Basic
// Java
public class hello {
public static void main(String args[]) {
System.out.print("Hello, world!");
}
}
因為不知道還有這麼個函數
puts函數功能雖然簡單,put的英文含義對於非英文母語也不難,但是並不夠。。。不夠計算機術語化
print的更為明確的英文含義更符合這個場景。
另外,我也贊同匿名用戶的說話,puts太過功能單一,而我們用hello world入門後乾的事情可不是puts能搞定的,還是用最常用的print來寫hello world吧因為 puts (3)是配合gets (3)使用的, 因為gets (3)存在安全問題, GNU C建議用 fgets (3) / fputs (3);
所以, 輪不到puts (3);ps. printf 家族函數很好用;
我覺得,用printf()是因為它的表面字義!讓初學者更容易理解接受!哪有那麼複雜!
1)只用一個函數搞定各種輸出方便又完美啊。2)puts自動加的換行,萬一是windows風格的,沒有精確的安全感啊。不僅puts少用,類似fputs寧願用fprintf,否則代碼總有隱患的時候
printf("printf涵蓋了puts的功能,如無必要,勿增實體。
")puts("雖然puts好像更美觀,但它唯一的優勢就是美觀,所以不常用。")printf("如果你用了不常用的puts,恐怕後果是puts與printf混用,丑。
")puts("該puts的時候printf還可以菊里力爭一下,該用printf的時候……啊,一般也不能用puts。")
推薦閱讀:
※C#與VC++在桌面軟體的開發比較?
※一行 JS (以分號結束)能實現什麼喪心病狂的功能?
※Matlab求一個矩陣中所有元素的平方和,兩種循環寫法為什麼性能相差很大?
※C 語言指針的指針和二維數組的區別?
※如何生成rest api文檔?
TAG:程序員 | 編程 | C編程語言 | HelloWorld程序 |