Fw: [問卦] 為甚麼C語言自訂函式一定要在主程式上面?

看板YOLO作者 ( )時間4年前 (2019/06/08 23:34), 編輯推噓0(000)
留言0則, 0人參與, 4年前最新討論串1/1
※ [本文轉錄自 Gossiping 看板 #1SzydGFl ] 作者: jserv (松鼠) 看板: Gossiping 標題: Re: [問卦] 為甚麼C語言自訂函式一定要在主程式上面? 時間: Wed Jun 5 21:55:19 2019 ※ 引述《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

06/05 21:55, 4年前 , 1F
06/05 21:55, 1F

06/05 21:56, 4年前 , 2F
hello world
06/05 21:56, 2F

06/05 21:56, 4年前 , 3F
前十
06/05 21:56, 3F

06/05 21:56, 4年前 , 4F
我也這麼覺得
06/05 21:56, 4F

06/05 21:57, 4年前 , 5F
快來推ㄍ不然被當文組
06/05 21:57, 5F

06/05 21:57, 4年前 , 6F
前十
06/05 21:57, 6F

06/05 21:57, 4年前 , 7F
先推
06/05 21:57, 7F

06/05 21:57, 4年前 , 8F
先推
06/05 21:57, 8F

06/05 21:58, 4年前 , 9F
這不是基本的嗎
06/05 21:58, 9F

06/05 21:58, 4年前 , 10F
06/05 21:58, 10F

06/05 21:58, 4年前 , 11F
嗯嗯嗯 就是這樣
06/05 21:58, 11F

06/05 21:59, 4年前 , 12F
06/05 21:59, 12F

06/05 21:59, 4年前 , 13F
看不懂
06/05 21:59, 13F

06/05 22:00, 4年前 , 14F
大大安安推一個
06/05 22:00, 14F

06/05 22:00, 4年前 , 15F
推一下 免得被說看不懂
06/05 22:00, 15F

06/05 22:00, 4年前 , 16F
06/05 22:00, 16F

06/05 22:00, 4年前 , 17F
06/05 22:00, 17F

06/05 22:00, 4年前 , 18F
看到這篇好像我不是CS的一樣QQ
06/05 22:00, 18F

06/05 22:01, 4年前 , 19F
朝聖
06/05 22:01, 19F

06/05 22:01, 4年前 , 20F
跪著推
06/05 22:01, 20F

06/05 22:01, 4年前 , 21F
這就是為什麼我恨C
06/05 22:01, 21F

06/05 22:01, 4年前 , 22F
專業
06/05 22:01, 22F

06/05 22:02, 4年前 , 23F
06/05 22:02, 23F

06/05 22:02, 4年前 , 24F
116一定是廢文 幫補血
06/05 22:02, 24F

06/05 22:02, 4年前 , 25F
淦 這樣摸不到C罩拉
06/05 22:02, 25F

06/05 22:02, 4年前 , 26F
大神又出來普渡眾生了
06/05 22:02, 26F

06/05 22:02, 4年前 , 27F
看不懂還是要推
06/05 22:02, 27F

06/05 22:02, 4年前 , 28F
嗯嗯 我也是這樣想的
06/05 22:02, 28F

06/05 22:02, 4年前 , 29F
CCC
06/05 22:02, 29F

06/05 22:03, 4年前 , 30F
看不懂
06/05 22:03, 30F

06/05 22:03, 4年前 , 31F
06/05 22:03, 31F

06/05 22:03, 4年前 , 32F
恩恩跟我想的一樣 只是我懶的打
06/05 22:03, 32F

06/05 22:03, 4年前 , 33F
每次線上講座必看,可惜在新竹上班,不然就去旁聽了
06/05 22:03, 33F

06/05 22:04, 4年前 , 34F
我也是這麼想的
06/05 22:04, 34F

06/05 22:04, 4年前 , 35F
朝聖推
06/05 22:04, 35F

06/05 22:04, 4年前 , 36F
講古
06/05 22:04, 36F

06/05 22:04, 4年前 , 37F
老闆問我為什麼跪著上班
06/05 22:04, 37F

06/05 22:05, 4年前 , 38F
這個釣到jserv太扯
06/05 22:05, 38F

06/05 22:05, 4年前 , 39F
06/05 22:05, 39F
還有 203 則推文
06/06 07:13, 4年前 , 243F
嗯嗯
06/06 07:13, 243F

06/06 07:24, 4年前 , 244F
06/06 07:24, 244F

06/06 07:44, 4年前 , 245F
我資料結構學期成績0分
06/06 07:44, 245F

06/06 08:15, 4年前 , 246F
我...我看不懂
06/06 08:15, 246F

06/06 08:18, 4年前 , 247F
跟我想的一樣
06/06 08:18, 247F

06/06 08:20, 4年前 , 248F
文組路過
06/06 08:20, 248F

06/06 08:25, 4年前 , 249F
有神快推
06/06 08:25, 249F

06/06 08:26, 4年前 , 250F
資工人表示:
06/06 08:26, 250F

06/06 08:26, 4年前 , 251F
看不懂
06/06 08:26, 251F

06/06 08:36, 4年前 , 252F
06/06 08:36, 252F

06/06 08:38, 4年前 , 253F
理科推
06/06 08:38, 253F

06/06 08:45, 4年前 , 254F
我國小電腦課就想到了
06/06 08:45, 254F

06/06 08:46, 4年前 , 255F
拜請拜請
06/06 08:46, 255F

06/06 09:28, 4年前 , 256F
好強,但看得懂的沒幾個
06/06 09:28, 256F

06/06 09:36, 4年前 , 257F
教書系的?!
06/06 09:36, 257F

06/06 10:02, 4年前 , 258F
有神快拜
06/06 10:02, 258F

06/06 10:10, 4年前 , 259F
推 這文章太棒 值得收藏~~~
06/06 10:10, 259F

06/06 10:12, 4年前 , 260F
有神快拜
06/06 10:12, 260F

06/06 10:15, 4年前 , 261F
我不想摸c了,我要g
06/06 10:15, 261F

06/06 10:16, 4年前 , 262F
06/06 10:16, 262F

06/06 10:45, 4年前 , 263F
06/06 10:45, 263F

06/06 11:03, 4年前 , 264F
老師好
06/06 11:03, 264F

06/06 11:23, 4年前 , 265F
雖然學過 但都忘光了QQ
06/06 11:23, 265F

06/06 11:29, 4年前 , 266F
長知識了
06/06 11:29, 266F

06/06 11:33, 4年前 , 267F
太神
06/06 11:33, 267F

06/06 11:41, 4年前 , 268F
看不懂的上Complier都在睡覺
06/06 11:41, 268F

06/06 12:34, 4年前 , 269F
只有寫過C-- 嗚嗚嗚嗚嗚
06/06 12:34, 269F

06/06 12:37, 4年前 , 270F
不知到但感覺很屌
06/06 12:37, 270F

06/06 13:10, 4年前 , 271F
你資工系?
06/06 13:10, 271F

06/06 17:04, 4年前 , 272F
有神快拜
06/06 17:04, 272F

06/06 20:18, 4年前 , 273F
推,Linker取名ld,所以Linker和Loader是有淵源的吧?
06/06 20:18, 273F

06/06 20:22, 4年前 , 274F
譬如說在link及load階段,都會做linking和relocation
06/06 20:22, 274F

06/06 21:11, 4年前 , 275F
@HowLeeHi, 不僅有淵源,早期根本就是一體的 :-)
06/06 21:11, 275F

06/06 21:11, 4年前 , 276F
可參照「你所不知道的 C 語言」系列講座,有兩項linker相關
06/06 21:11, 276F

06/06 21:12, 4年前 , 277F
@balcony5566, 一定是你的記事本軟體不好用,在此誠心建議
06/06 21:12, 277F

06/06 21:13, 4年前 , 278F
改用有媽祖加持的編輯器: Mazu Editor!
06/06 21:13, 278F

06/06 21:13, 4年前 , 279F

06/06 22:07, 4年前 , 280F
先跪
06/06 22:07, 280F

06/07 03:41, 4年前 , 281F
老師我愛你
06/07 03:41, 281F
※ 發信站: 批踢踢實業坊(ptt.cc) ※ 轉錄者: okcool (125.230.18.220 臺灣), 06/08/2019 23:34:45
文章代碼(AID): #1S-zMMsN (YOLO)