C語言中的函數對應C#/Java的方法,是結構化編程的基本單元。本文深入剖析函數聲明與定義的分離、頭文件機制、編譯鏈接四階段,以及模組化開發的最佳實踐。
// 函數聲明(原型)
int sum(int a, int b);
int div(int a, int b);
// 函數定義
int sum(int a, int b) { return a + b; }
int div(int a, int b) { return a / b; }
// 調用
int main() {
printf("sum=%d, div=%d\n", sum(100,200), div(300,100));
return 0;
}
關鍵點:C語言編譯器按文件順序單遍掃描,調用前必須見到聲明或定義。否則會隱式假定返回int,導致錯誤。
將聲明放入頭文件,定義放入源文件,主程序包含頭文件即可調用。
// Calculate.h int sum(int a, int b); int div(int a, int b);
// Calculate.c
#include "Calculate.h"
int sum(int a, int b) { return a + b; }
int div(int a, int b) { return a / b; }
// main.c #include#include "Calculate.h" int main() { printf("sum=%d, div=%d\n", sum(100,200), div(300,100)); return 0; }
#include、#define等偽指令,展開頭文件內容,生成.i中間文件。#include "Calculate.h"實質是將頭文件內容原文複製到main.c中。.c編譯為匯編.s,再生成目標文件.obj(機器碼+符號表)。此階段只檢查語法、類型,不解決跨文件符號引用。.obj及庫文件合併,解析符號引用(如sum在Calculate.obj中定義),重定位地址,生成最終.exe可執行文件。#include "Calculate.c"?若主文件包含Calculate.c,預處理後main.c包含函數定義;同時Calculate.c單獨編譯也產生Calculate.obj。鏈接時sum符號出現兩次(一次在main.obj,一次在Calculate.obj),報重複定義錯誤。正確做法:只包含聲明(.h),定義(.c)單獨編譯鏈接。
Project/
├── main.c
├── Calculate.h
├── Calculate.c
└── Debug/
├── main.obj
├── Calculate.obj
└── Project.exe
#ifndef CALCULATE_H #define CALCULATE_H ... #endif。int sum(int a, int b);比int sum(int, int);可讀性強,現代編譯器均支持。static:限制鏈接作用域,避免符號污染。掌握.h/.c分離與編譯鏈接流程,是從「寫代碼」邁向「工程化開發」的關鍵一步。