sponsored links
    
※ 引述《fragmentwing (片翼碎夢)》之銘言:
: 如題
: 最近終於開始自學C語言
: 為甚麼C語言一定至少要放個原型在主程式上方才行?
: 或者說,明明都是一行一行讀取,其他語言是怎麼做到可以把函式到處亂擺的

這問題非常好,我不知為何會引來負面聲音,可能是原發問人沒有把「其他語言」清楚
標示出來吧?抑或是問題太簡短呢?有趣的問題如果被忽略,那真是太可惜。

其實由 Dennis M. Ritchie (以下簡稱 dmr) 開發的早期 C 語言編譯器 [1] 沒有明確
要求 function prototype 的順序。dmr 在 1972 年發展的早期 C 編譯器,原始程式碼
後來被整理在名為 "last1120c" 磁帶中 [2],我們如果仔細看 c00.c 這檔案,可發現
位於第 269 行的 mapch(c) 函式定義,在沒有 forward declaration [3] 的狀況下,
就分別於第 246 行和第 261 行呼叫,奇怪吧?

而且只要再瀏覽 last1120c 裡頭其他 C 語言程式後,就會發現根本沒有 #include 或
#define 這一類 C preprocessor [4] 所支援的語法,那到底怎麼編譯呢?在回答這問題
前,摘錄 Wikipedia 頁面的訊息:
> As the C preprocessor can be invoked separately from the compiler with
> which it is supplied, it can be used separately, on different languages.
> Notable examples include its use in the now-deprecated imake system and for
> preprocessing Fortran.

原來 C preprocessor 以獨立程式的形式存在,所以當我們用 gcc 或 cl (Microsoft
開發工具裡頭的 C 編譯器) 編譯給定的 C 程式時,會呼叫 cpp (伴隨在 gcc 專案的
C preprocessor) 一類的程式,先行展開巨集 (macro) 或施加條件編譯等操作,再來
才會出動真正的 C 語言編譯器 (在 gcc 中叫做 cc1)。值得注意的是,1972-1973 年
間被稱為 "Very early C compilers" 的實作中,不存在 C preprocessor (!),當時
dmr 等人簡稱 C compiler 為 "cc",此慣例被沿用至今,而無論原始程式碼有幾個檔
案,在編譯前,先用 cat [5] 一類的工具,將檔案串接為單一檔案,再來執行 "cc"
以便輸出對應的組合語言,之後就可透過 assembler (組譯器,在 UNIX 稱為 "as")
轉換為目標碼,搭配 linker (在 UNIX 稱為 "ld") 則輸出執行擋。

所以說,在早期的 C 語言編譯器,強制規範 function prototype 及函式宣告的順序
是完全沒有必要的,要到 1974 年 C preprocessor 才正式出現在世人面前,儘管當時
的實作仍相當陽春,可參見 dmr 撰寫的 "The Development of the C Language" [6]
C 語言的標準化是另一段漫長的旅程,來自 Bell Labs 的火種,透過 UNIX 來到研究
機構和公司行號,持續影響著你我所處的資訊社會。

你或許會好奇,function prototype 的規範有什麼好處呢?這就要從 "Rationale for
International Standard -- Programming Languages -- C" [7] 閱讀起,依據 C9X
RATIONALE 的第 70 頁 (PDF 檔案對應於第 78 頁),提到以下的解說範例:

    extern int compare(const char *string1, const char *string2);

    void func2(int x) {
        char *str1, *str2;
        // ...
        x = compare(str1, str2);
        // ...
    }

編譯器裡頭的最佳化階段 (optimizer) 可從 function prototype 得知,傳遞給函式
compare 的兩個指標型態參數,由於明確標注了 "const" 修飾子,所以僅有記憶體地
址的使用並讀取相對應的內容,但不會因為修改指標所指向的記憶體內容,從而沒有產生
副作用 (side effect)。這樣編譯器可有更大的最佳化空間,可對照「你所不知道的 C
語言:編譯器和最佳化原理篇」,得知相關最佳化手法。

一如 C9X RATIONALE 提到,C 語言和其他受 Algol 影響的程式語言,都具備 function
prototype 機制,這使得編譯時期,就能進行有效的錯誤分析和偵測。無論是 C 語言、
B 語言,還是 Pascal 語言,都可追溯到 ALGOL 60 [9]。

ALGOL 是Algorithmic Language (演算法使用的語言) 的縮寫,提出巢狀 (nested) 結構
和一系列程式流程控制,今日我們熟知的 if-else 語法,就在 ALGOL 60 出現。
ALGOL 60 和 COBOL 程式語言並列史上最早工業標準化的程式語言。
可參見本看板 #1SdKXN4t

程式語言的演化,深受底層工具和硬體限制的影響,這次探討的 function  prototype
及函式宣告的順序,其實就反映出編譯器演化的歷程。人類史上第一個編譯器,A-0
System 開發於 1951-52 年間,注意到當時的用語是 "System",而且名稱 A-0 代表
Arithmetic Language version 0,與其說是今天我們提及的高階語言編譯器,不如說是
程式的載入器 (loader) 或連結器 (linker)。
相關訊息可參見本看板 #1RhWSNPG

黑格爾在其 1820 年的著作「法哲學原理」提到: (德語原文)
> Was vernuftig ist, das ist wirklich;
> und was wirklich ist, das ist vernuftig.

英語可解讀為 "What is rational is actual and what is actual is rational.",
像是 C 語言這樣的工業標準,至今仍活躍地演化,當我們回顧發展軌跡時,凡是合乎
理性 (vernuftig),也就必然會出現、或成為現實 (wirklich),反過來說也成立。

甚至我們可推敲 C9X RATIONALE 字裡行間,每個看似死板規則的背後,其實都可追溯出
像是上方的討論。

歡迎關注「你所不知道的 C 語言」系列講座:
    https://hackmd.io/@sysprog/HJpiYaZfl

千萬別忘了 C 語言的發展就是為了開發 UNIX 作業系統和相關系統程式,而 Linux 核心
自然就是將 UNIX 精神發揚光大的智慧結晶,歡迎關注「Linux 核心設計」課程,附有
線上教材:
    http://wiki.csie.ncku.edu.tw/linux/schedule

[1] Very early C compilers and language,
    https://www.bell-labs.com/usr/dmr/www/primevalC.html
[2] 位於 GitHub 的副本,
    https://github.com/mortdeus/legacy-cc/
[3] https://en.wikipedia.org/wiki/Forward_declaration
[4] https://en.wikipedia.org/wiki/C_preprocessor
[5] cat 工具程式的作用是 "concatenate and print file",
    https://www.unix.com/man-page/posix/1posix/cat/
[6] The Development of the C Language,
    https://www.bell-labs.com/usr/dmr/www/chist.html
[7] Rationale for International Standard -- Programming Languages -- C
    http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf
[8] 你所不知道的 C 語言:編譯器和最佳化原理篇,
    https://hackmd.io/@sysprog/Hy72937Me
[9] Algol 60,
    https://en.wikipedia.org/wiki/ALGOL_60

--

    

※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.116.82.61 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Gossiping/M.1559742928.A.3EF.html
XXXXHAY: 頭 06/05 21:55
Costco5566: hello world 06/05 21:56
sujianwei20: 前十 06/05 21:56
moswu: 我也這麼覺得 06/05 21:56
jiajia1: 快來推ㄍ不然被當文組 06/05 21:57
Ericz7000: 前十 06/05 21:57
he00504616: 先推 06/05 21:57
angerD: 先推 06/05 21:57
siamese: 這不是基本的嗎 06/05 21:58
a22918097: 推 06/05 21:58
VXcc: 嗯嗯嗯 就是這樣 06/05 21:58
ggBird: 神 06/05 21:59
fox875566: 看不懂 06/05 21:59
Cybershit: 大大安安推一個 06/05 22:00
Friend5566: 推一下 免得被說看不懂 06/05 22:00
redDest: 推 06/05 22:00
landysh: 推 06/05 22:00
lturtsamuel: 看到這篇好像我不是CS的一樣QQ 06/05 22:00
rewrite404: 朝聖 06/05 22:01
g5637128: 跪著推 06/05 22:01
pzyc79: 這就是為什麼我恨C 06/05 22:01
gungunme5566: 專業 06/05 22:01
brian1015: 推 06/05 22:02
Mesa5566: 116一定是廢文 幫補血 06/05 22:02
obdv: 淦 這樣摸不到C罩拉 06/05 22:02
barry910543: 大神又出來普渡眾生了 06/05 22:02
HowieH: 看不懂還是要推 06/05 22:02
NTULioner: 嗯嗯 我也是這樣想的 06/05 22:02
Turas: CCC 06/05 22:02
OGCOGCOGCOGC: 看不懂 06/05 22:03
TrevorStory: 推 06/05 22:03
salesperson: 恩恩跟我想的一樣 只是我懶的打 06/05 22:03
cjamhe01385: 每次線上講座必看,可惜在新竹上班,不然就去旁聽了 06/05 22:03
ymx3xc: 我也是這麼想的 06/05 22:04
compuworld: 朝聖推 06/05 22:04
hizuki: 講古 06/05 22:04
WYchuang: 老闆問我為什麼跪著上班 06/05 22:04
jackyT: 這個釣到jserv太扯 06/05 22:05
FlynnZhang: 卡 06/05 22:05
jimmy1999: 錢錢 06/05 22:05
allomifo: 推 06/05 22:06
tongzhou: 朝聖 06/05 22:06
eric21489: 太神啦 釣到ㄌ 06/05 22:06
tcfsh510: 推 朝聖 06/05 22:06
Ericz7000: 之前老師有去交大上物聯網什麼的課啊 06/05 22:06
faker007: 看無 06/05 22:07
choco7: 恩恩 跟我想得差不多 06/05 22:07
nqj: 嗯嗯對丫 06/05 22:08
jackwula9211: 不過C++某些時候還是很好用啊 06/05 22:08
u04rmp: 快推 06/05 22:09
terryshu: 推 06/05 22:09
andy188: 前百 06/05 22:09
max8568: 有神快拜 06/05 22:09
ZhouGongJin: 只能給個讚 06/05 22:09
q13461346: 跪了 06/05 22:09
rong1994: 嗯嗯 我也是這麼認為的 06/05 22:10
nicklyyyy: 嗯,跟我想說的差不多 06/05 22:11
mmonkeyboyy: 推一下 認真 還用RANDY的書 XD 06/05 22:11
ajason0753: 先跪再說 06/05 22:11
Hacker8246: 沒錯 就是這樣 06/05 22:12
jahfone: 那為什麼有些程式語言不這樣用呢? 06/05 22:13
devilkool: 神 06/05 22:13
Fice: 推 06/05 22:13
chaige: 跟我想得差不多 中間有地方小錯但無傷大雅 可以接受 06/05 22:13
DanielHAO: 恩恩跟我想的一樣 06/05 22:13
a0652qj: 完全看不懂,剛好也箭頭XD 06/05 22:13
ploveh: jserv下凡 06/05 22:13
hardway: 太會了吧 06/05 22:14
hohamita: 推 06/05 22:14
s0805744: 看完覺得大學對不起我教授 06/05 22:14
jserv: @jahfone, 最初C語言不用理會函式定義的順序,最終能夠處理 06/05 22:15
jserv: 符號(symbol)之間的相依狀況即可。是後來C語言才變嚴格的 06/05 22:15
kipi91718: 推! 好詳細長知識了 寫了這麼久的C都不知道標準來由 06/05 22:15
cattgirl: 你在寫期刊 06/05 22:17
jserv: @Ericz7000, 之前我在交大資工系還開了「自由開源軟體與 06/05 22:17
CityRanger: 廢物cs生看不懂 QQQQQ 06/05 22:17
jserv: 專案協作」: https://sites.google.com/site/fossapc/ 06/05 22:17
jserv: @kipi91718, 沒事,我只是練習打字,下次請鼓勵發問的人 06/05 22:18
donkilu: 推 06/05 22:19
mmonkeyboyy: 這本書台灣不是很多人用的 根本是OS基石 06/05 22:19
jserv: @jackwula9211, 針對 C++ 可講古的題材更多啊...嘶 06/05 22:20
iamnotme: 有神快拜 06/05 22:22
Gold740716: 但既然身為編譯式語言,完全可以分析完整份檔案再開始 06/05 22:23
smonke: 好~! 完全不懂...還是給推 06/05 22:23
justatree: 推 06/05 22:23
iverlung: 有神快拜 06/05 22:23
palapalanhu: 神 06/05 22:23
Gold740716: 最佳化吧?哪個在先哪個在後其實可以忽略。 06/05 22:24
jserv: @Gold740716, 涉及到 side effect 06/05 22:24
Gold740716: cs 這篇看不懂可以自盡了 06/05 22:24
kyrie77: 嗯嗯嗯 跟我想的差不多 06/05 22:25
amethystboy: 一定要先推 06/05 22:26
cattgirl: 你是不是成大教授 06/05 22:26
aa55667878: 推 06/05 22:26
lusifa2007: 快推一個不然人家以為我們不懂Xd 06/05 22:26
nonopig: 推 跟我想的是一樣 06/05 22:27
cattgirl: 我朋友交大教授 與你決一死戰 06/05 22:27
fjyang: 神 06/05 22:28
jserv: @cattgirl, 可以請你朋友等我大學畢業,再來決鬥嗎? 06/05 22:28
ry3298: 推 06/05 22:29
DarkerDuck: 推推 06/05 22:29
kis28519: 有神快拜 06/05 22:30
ccucwc: 認真推 06/05 22:32
roro0: 好強 XD 06/05 22:34
kingofage111: 推 06/05 22:35
ERT312: 學程式語言還要讀歷史 06/05 22:35
yuxds: 推 06/05 22:37
justastupid: 嗯嗯 你說的沒錯 06/05 22:41
wju1230: 有貓給推 06/05 22:41
ShittyFace: 先推再看 06/05 22:41
bmks: 推個 06/05 22:41
vita88: 好啦,我看不懂 06/05 22:42
Wand: 推 06/05 22:42
skhten: 怕 06/05 22:42
arsonlolita: 嗯嗯 06/05 22:42
ab37695543xs: 所以簡單的來說就是為了更容易在編譯時期找到錯誤與 06/05 22:46
ab37695543xs: 最佳化囉? 06/05 22:46
atpx: 算是有表達到我的想法, 給你75分 06/05 22:46
knme: 推 06/05 22:48
ljsnonocat2: 有神快拜 06/05 22:51
sismiku: 恩 跟我想的差不多 06/05 22:52
KNVSEOC: 就算一知半解也要推 06/05 22:53
minicoke: 德文你也懂? 06/05 22:55
pazoo: 推 06/05 22:55
derekjj: 有神快拜 06/05 22:56
kiuan: 推 06/05 22:56
gakaza: 跪推 +1 06/05 22:57
fallen01: 推 06/05 22:59
FJHS: 朝聖 06/05 23:02
scoutpioneer: 嗚嗚身為理組還是看不懂 06/05 23:03
jserv: @ab37695543xs, 回顧程式語言的發展,人類的想像力很豐富, 06/05 23:04
asiamistborn: 7777777777777 06/05 23:04
jserv: 像是LISP這類對應到數學抽象思考的語言,很早就提出了。但C 06/05 23:04
jserv: 卻走了實務導向的路途,也就是一方面讓語言本身定義嚴謹, 06/05 23:05
jserv: 另一方面確保編譯器和連結器得以有效實作出來 06/05 23:05
derson: 只能跪著推了 06/05 23:05
silentduke: 朝聖推 06/05 23:06
yoshihuang8: 推 06/05 23:06
pandatom: 朝聖jserv 06/05 23:07
voyhanxu: 快推!免得被別人發現我文組的! 06/05 23:07
frk2z125: 推 以前計算機很弱,對於記憶體與size更是斤斤計較, 所 06/05 23:09
frk2z125: 以能從人這邊規範就規範 06/05 23:09
qwer338859: 神 06/05 23:10
Missnanako: 嗯嗯 06/05 23:11
Misoshiru: 嗯嗯我也是這麼想的 只是懶得打 06/05 23:13
ericleft: 原來如此 06/05 23:13
lainhoter: 初音只是個軟體 06/05 23:14
vasia: 全台文組同學深表贊同 06/05 23:15
danny30715: 朝聖 06/05 23:15
blackman5566: 寫了大半輩子程式也看不懂這篇在說什麼 只能推了 06/05 23:16
probity: 我早告訴過你了 06/05 23:18
schumi7401: 正如我想 06/05 23:20
lolitass: 趕快推 以免被發現完全看不懂 06/05 23:21
youngglasses: 簡單說就是為了最佳化啦.... 越早將宣告的部分寫出 06/05 23:23
youngglasses: 在轉換的初期處理的時候就可以更好的安排資源 06/05 23:23
mike40709: 沒錯跟我想的一樣 06/05 23:23
xu3ru0454: 你及格了! 06/05 23:23
blackbottle: 對對對沒錯沒錯 就是這樣 我也是這麼覺得 只是還沒來 06/05 23:25
blackbottle: 得及寫文章 06/05 23:25
Everyeeeee: 我知道啊 06/05 23:25
isisss: 嗯嗯 我也這樣覺得 06/05 23:26
gabriel: 八卦好文必須推 06/05 23:28
amALu: ......... 06/05 23:31
eric112: 原來大家都這樣想 06/05 23:32
fg008kimo: 好聞必推 06/05 23:32
SamuelLuo: 推,沒想到還能看到德文 06/05 23:36
liaon98: 跪著讀 06/05 23:36
erre: 這其實真的很基本…… 06/05 23:37
Account4PTT: 推 06/05 23:39
bbo6uis122: 推 06/05 23:40
RoaringWolf: 恩恩,對,就這樣嘛,恩 06/05 23:41
Bright: 嗯嗯 對 06/05 23:45
zs84: 推 06/05 23:47
loet: 推 06/05 23:48
omegajoker: 推 06/05 23:49
coolda: 先推再看 06/05 23:50
notneme159: 推個 06/05 23:53
tommy6300167: 跟我想的差不多 打到一半被你先回答了 06/05 23:53
ck030561: 唉 本來想開示的 你都講完了 06/05 23:54
MagicSword: 嗯嗯,我也這樣覺得。 06/05 23:54
randy061: 雖推,但太硬了… 無法看完 06/05 23:55
shishe: 推推 學了C語言 但看到你的之後感覺什麼都沒學過 06/05 23:55
imaxpayne: 跟我想的一樣 06/05 23:56
Matz: 推推 06/05 23:57
platinum5566: 長知識了 06/05 23:59
a5245242003: 推 06/06 00:00
panda04056: 推推 06/06 00:00
tweence: 06/06 00:05
tom83615: 嗚嗚嗚我廢物 只看得懂3成 06/06 00:07
qscez: 推 06/06 00:07
jai166: 竟然釣到大神 06/06 00:07
rex662624: 推個 06/06 00:14
rog43: 感謝老師賜教 06/06 00:16
rfireptt: 原來是大神,真的寫的很好,淺顯易懂 06/06 00:21
jeromeshih: 推 06/06 00:22
ffffffffff: 大神 06/06 00:24
jim0611tw: 真的太強 受小弟一拜 06/06 00:24
Kent1313: 有神,快推 06/06 00:30
milker: 我忙到現在就被你先回文了 可惜 06/06 00:33
UROLOGY: 跟我想的差不多 06/06 00:35
fragmentwing: 原來一開始也沒被規範啊 淚推大神教授 06/06 00:41
charlie0112: 跟我想的一樣 06/06 00:42
hakosaki: 不愧是jserv大大 06/06 00:42
jkreg: 果然是我大116 06/06 00:46
stw0975: 推 06/06 00:50
abc53: 這感覺好無趣 06/06 00:52
billccchang: j神快推! 06/06 00:56
fragmentwing: 再推 06/06 00:57
matt4424: 太神啦 06/06 01:00
nullife: 太神啦 06/06 01:08
erwinia: 推 06/06 01:08
patrickwu2: 太神啦 06/06 01:13
gyman7788: 對啊,跟我國小學的差不多正確 06/06 01:15
blackbottle: 對對 再推一次 06/06 01:16
balcony5566: 還在記事本打文章草稿就被你搶先了 可惜 06/06 01:17
fragmentwing: 再三推 06/06 01:29
fragmentwing: 推 06/06 01:34
chingyi071: 只能推了 06/06 01:52


網友評論

sponsored links

搜尋主題

sponsored links
sponsored links

推薦閱讀

大家正在看

sponsored links
BTrend 2018 Abuse form