標籤:

如何說服同學在寫C++程序的時候用cstdio而不是stdio.h?


& 已經是 deprecated。

N4606 C5.1:

C.5.1 Modifications to headers [diff.mods.to.headers]

1 For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in D.4, but their use is deprecated in C++.

C++ Standard Library header files

clang-tidy - modernize-deprecated-headers


使用std namespace的好處在於避免污染global namespace,然而cstdio並不能做到這一點。更何況cstdio裡面還有一大坨東西不在std namespace下面,真用起來那就是std::和::摻雜著揉在一起。

所以使用cstdio非但沒有獲得應有的好處,反而會讓代碼風格更加混亂。


我認為這是 C++ 標準的敗筆,沒什麼明顯的好處,卻造成了代碼的混亂。首先,寫 non-trivial C++ 程序不可避免地要使用 .h 的頭文件,追求頭文件的「純潔性」沒有意義。要是只用「標準庫」,C++ 程序能做的事情實在很有限,特別在 IO 方面只能讀寫普通文件,連目錄都不能處理,更別說網路、音頻、視頻、圖形界面、進程管理及進程間通信等等了。操作系統往往用 .h 頭文件提供以上功能。

正確的做法是 man page 說用哪個 header 就用哪個 header。具體一點:

  • assert() 是個 macro,你 include cassert 還是不能用 std::assert。
  • errno 也是個 macro,你 include cerrno 也還是不能用 std::errno。

  • 你想用 poll(2),man page 告訴你要 include poll.h,你要不要試試 cpoll ?
  • 你想檢查內存泄漏,MSDN 告訴你要 include crtdbg.h,你要不要試試 ccrtdbg?Windows.h 要不要試試 cwindows 或 cWindows 或 CWindows ?
  • 你想列目錄,APUE 告訴你要 include dirent.h,你要不要試試 cdirent?
  • 你想搞網路編程,UNP 告訴你要用 arpa/inet.h、netinet/in.h、sys/socket.h 等等,你要不要去找它們的 C++ 對應物?
  • 你寫 pthreads,是 include pthread.h 還是 cpthread?
  • 你想調用 fcntl(),是 include fcntl.h 還是 cfntl ?
  • 你想調用 fork()/pipe()/chdir() 等等,man page 告訴你要 include unistd.h,你要不要試試 cunistd?
  • 你想調用 gettimeofday(),man page 告訴你要 include sys/time.h,你要不要試試 sys/ctime 或 csys/time.h?
  • 你想調用 gmtime_r(),man page 告訴你要 include time.h,你知道 C++ 有 ctime 這個 header,但是 include 之後卻發現 std::gmtime_r 不存在,還是得用 ::gmtime_r(),何苦多此一舉?還有 timegm()。
  • 就拿你用的 cstdio 來說,其中聲明的 EOF、popen()、stdin 等等宏/函數/變數並不位於 std 中,你寫 std::stdin 是錯的。如果使用 cstdio,你還得記住哪些函數是 C++ 承認的,位於 std namespace,哪些是 C/POSIX 的,位於全局 namespace。比如 getc() 和 getc_unlocked() 就位於不同的 namespace,因為 stdio.h 不僅包含 C 標準庫的內容,還包含POSIX以及尚未標準化的額外功能。比如 snprintf 這個早於 C99 就存在的函數,到 C++11 里才進入 std namespace,那你是用 ::snprintf() 還是 std::snprintf() ?

要想遵循C++標準的建議使用這些新的頭文件來調用C庫,你不光要記住哪些C頭文件有對應的C++版,還要記住哪些符號(標識符)定義在std namespace,哪些定義在 global namespace,就算做到了前面這兩點,你的代碼中使用C庫的地方還是會混用 std:: 和 ::,造成風格不一致。何必給自己找麻煩,C++ 標準庫之外的內容乾脆統一用 .h 頭文件好了。


你應該反思的是你為什麼有那麼多時間去說服別人從1998年的時空穿越到2016年。時間旅行不是違法的嗎?


為何?

實測,stdio.h和cstdio單單是scanf就效率不一樣,stdio.h快了將近一倍,所以在要求讀入效率的情況下,我會用stdio.h。

有哪位大牛能解釋一下嗎?


告訴他寫cstdio能夠裝逼把妹


這個貼暴露了很多人僅僅是形而上學。


如果你可以改用cstdio,我就讓你嘿嘿嘿


莫裝逼

(可能你自己覺得不是,但是對你同學來說可能就是,而且別人的事管這麼幹嘛?我當年也是stdio.h用了很多年了,兩者差別只是一個namespace而已,要改這個習慣,等他覺得有必要了,要改也是很方便的。


為啥不直接讓他用iostream?

/*======================================*/

另外, @陳碩 提到的那些庫,不能帶 c 引用的原因是帶 C 的那些是 C++ STL 做了處理,用 cstdio 舉例子,cstdio中是定義 namespace std 後 #include &。第三方庫沒有這樣處理,因此不能加 c 包含。

證明一下:

環境:Windows 10 Build 14393,Code::Blocks 16.01,MinGW 4.9.2

第 42 行:

#include &

第 96 - 147 行,在 namespace std 中用 using 指令將 stdio.h 中的函數定義等導入到 namespace std 中。

在 Linux 下,/usr/include/c++/5/cstdio 文件內容與上述文件相同。

另外,說到有的函數沒被導入 std 里,這個問題很好解決啊,只要 using namespace std 以後,所有的都不用加限定,多省事兒。


隨口說一句,說stdio.h已經過時棄用了咯。如果他不聽或者無動於衷,那麼多半對c++也沒啥興趣,以後要是工作了盡量少和他搭在一個組就好了。畢竟以後你們可能還會為移動構造函數、初始化列表,用不用lambda,簡化版的for,auto等等東西吵起來。

當然更多的可能是他以後會挑個其他語言的活(逃


mingw-w64: slow sprintf in amp;

貌似stdio.h要快

....


cstdio 是c++的標準庫頭文件,stdio.h是c的標準庫頭文件。

寫c++程序優先用c++標準庫,這就是很好的說服人的理由。


估計沒看c++primer(攤手

那你問問他 #include &

還是#include &

尤其是遇到同時用string類的時候#include &....

用.h混合看著不難過嗎


你是非要和一群程序猿爭辯哪種語言最好咯o( ̄ヘ ̄o#)


新換的電腦,新裝的vs2015……

試試有沒有問題,發現「hello world」都打不出來了……因為&沒有被發現……

改用&吧……


c++單方面宣布stdio.h deprecated但是沒給出任何理由,也沒人鳥他。


剛學編程的表示書上只有stdio.h


嘛,其實你可以告訴他:cstdio比stdio.h少打一個點啊!

如果你同學是懶癌晚期就會聽你的了。


這也從側面說明這個同學對技術沒有追求,不要管他,將來你可以少一個競爭者,多一塊墊腳石。


推薦閱讀:

當你寫幾萬行代碼時,你在寫什麼?
有什麼現有函數,輸入是一個單詞變式的字元串,如複數,過去式,現在進行時等,輸出這個單詞的原型?
如何評價開學季知乎上大量出現C/C++新手問作業題?
為什麼有些人罵 C++,如 Linux 之父對 C++ 進行了炮轟,說它是糟糕程序員的垃圾語言?
C++中if(x==8)和if(8==x)有什麼區別?

TAG:編程 | C | 頭文件 |