程式的本質可以用一句經典公式概括:程式 = 演算法(靈魂)+ 資料結構(加工對象)+ 程式設計方法 + 語言(工具)。而 #include <stdio.h> 這一行代碼,往往是我們踏入 C 語言編程世界的第一步。今天,我們就從這裡出發,層層剖析程式碼背後的編譯、鏈接與執行全流程。
當我們使用 printf、scanf 等標準庫函數時,編譯系統要求我們在編譯前透過 #include 導入對應的頭文件。以 stdio.h 為例,它本質上包含了巨集定義(如 NULL、EOF)、條件編譯指令以及函數聲明:
/* stdio.h 片段 */ #ifndef _STDIO #define _STDIO #define NULL _NULL #define EOF -1 #define BUFSIZ 512 /* 函數聲明 */ int fclose(FILE *); int printf(const char *, ...); int scanf(const char *, ...); /* ... */ #endif
實際的函數定義則位於標準庫的原始碼中(如 printf.c),並最終依賴作業系統提供的 API(如 Linux 的 glibc、Windows 的 Windows API)完成底層操作。大致流程:頭文件聲明 → 標準庫實現 → 原始碼調用 → 作業系統 API 執行。
從上至下:
.o/.obj) → 透過作業系統介面(API)調用以 hello.c 為例:
#include <stdio.h>
void main() { printf("Hello world"); }
hello.c + stdio.h → hello.i#define,展開巨集定義#if 等)#include,將頭文件內容插入當前位置hello.i → hello.s(產生匯編碼)注意:此階段均與目標機器無關。
hello.s → hello.o(產生目標檔案)此時變數/函數仍未分配實際記憶體位址,將在鏈接階段完成。
hello.o + 標準庫.o → 可執行檔核心任務:解決模組間通訊(變數/函數的絕對位址引用)。
庫本質上是一組打包的目標檔案;執行階段庫提供程式運行的基本函數集合。
.so/.dll),節省記憶體,便於更新。預先編譯好但未鏈接的目標檔案集合(C 的 .o、Java 的 .class),透過 #include 或 import 獲得存取權限。include 是文本插入,import 是路徑引用。
.exe?原始碼 → 編譯為目標檔 → 打包為 APK → 安裝到手機 → 運行時由 ART/Dalvik 虛擬機解釋/編譯執行,動態鏈接系統 API。
| 類別 | 代表語言 | 方式 | 優點 | 缺點 |
|---|---|---|---|---|
| 直接編譯 | C, C++, VB | 源碼 → 機器碼 | 執行速度快 | 平台相關,需重新編譯 |
| 直接解釋 | HTML, JavaScript | 逐行解釋執行 | 跨平台 | 速度慢,原始碼易洩露 |
| 中間碼+虛擬機 | Java, .NET | 源碼 → 位元碼 → JVM/CLR | 跨平台、安全、GC | 啟動較慢、效能略低於原生 |
auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static
分類:資料類型關鍵字(int, float...)與流程控制關鍵字(if, while...)。關鍵字不可作變數/函數名使用。