6.3 大程式結構
阿新 • • 發佈:2019-01-06
1.多個 .c檔案,如何編譯
- main()裡的程式碼太長,適合分成幾個函式
- 一個原始碼檔案太長,適合分成幾個檔案
- 兩個獨立的原始碼檔案 不能編譯成一個可執行程式
之前我們寫的程式碼,是放在一個.c檔案中,如果main寫在一個.c檔案中,max()寫在一個.c檔案中呢?
2.專案
- 新建專案: Devcpp中 檔案 —— 新建 —— 專案 —— Console Application
- 對於專案,Devcpp 的編譯會把一個專案中的所有原始碼檔案都編譯後,連結起來
- 有的IDE有 編譯 和 構建 兩個按鈕,編譯 是對單個原始碼檔案編譯,構建是對整個專案做連結
3.編譯單元
- 一個.c檔案就是一個編譯單元
- 編譯器每次編譯只處理一個編譯單元
4.標頭檔案
把函式原型 放到一個 以.h結尾的標頭檔案中,在需要呼叫這個函式的 .c 原始碼檔案中 #include這個標頭檔案,編譯器在編譯的時候就知道函式的原型了
新建——原始碼——max.h
max.h
double max(double a,double b);
max.c
#include "max.h"
double max(double a,double b)
{
return a > b ? a : b;
}
main.c
#include <stdio.h>
#include "max.h"
int main(void) {
double a = 5;
double b = 6;
printf("max is %f\n", max(5, 6)); // max is 6.000000
return 0;
}
5.#include
- #include是一個編譯預處理命令,和巨集一樣,在編譯之前就處理了
- 編譯時,把標頭檔案的全部文字內容 原封不動地 插入到 include所在的地方
5.1 “” 還是 <>
- #include 有兩種形式來指出要插入的檔案
- ”“編譯時,編譯器首先在當前目錄(.c檔案所在的目錄)尋找這個檔案,如果沒有 就到指定目錄去找
- <>編譯時,編譯器只在指定的目錄去找
- 編譯器知道標準庫的標頭檔案在哪裡
- 環境變數 和 編譯器命令列引數 也可以指令標頭檔案的目錄
5.2 誤區
- #include 不是用來引入庫的
- 現在的C語言編譯器預設會引入所有的標準庫
#include <stdio.h> 只是為了讓編譯器知道 printf函式的原型,保證你呼叫時給出的引數值是正確的型別
stdio.h 裡只有printf()的原型,printf的程式碼在另外的某個 .lib(Windows)或.a(Unix)中
6 標頭檔案
- 一般的做法是 任何 .c 都有對應的同名的.h,把所有對外公開的函式原型 和 全域性變數的生命 都放進去
- 在使用 和 定義 這個函式的地方都應該 #include 這個標頭檔案
7.宣告
7.1 宣告與定義
int i; // 變數的定義
extern int i; // 變數的宣告
- 宣告是不產生程式碼的
- 函式原型
- 變數原型
- 結構宣告
- 巨集宣告
- 列舉宣告
- 型別宣告
- inline函式
- 定義是產生程式碼的
7.2 宣告的使用
- 只有宣告可以放在標頭檔案中(是規則不是法律)
- 否則會造成一個專案中多個編譯單元裡有重名的實體
- 某些編譯器允許幾個編譯單元中存在同名的函式,或者用weak修飾符來強調這種存在
7.3 重複宣告
- 同一個編譯單元裡,同名的結構不能被重複宣告
- 如果標頭檔案裡有 結構的宣告,很難保證 這個標頭檔案 不會在一個編譯單元裡 被#include多次
- 需要“標準標頭檔案結構”
- 運用條件編譯和巨集,保證這個標頭檔案在一個編譯單元中只會被#include一次
- #pragma once 也能起到相同的作用,但是不是所有的編譯器都支援
錯誤示例:
struct Node{
int value;
char* name;
};
// [Error] redefinition of 'struct Node' 重新定義 struct Node
struct Node{
int value;
char* name;
};
int main(void) {
return 0;
}
標準寫法:
max.h
#ifndef _MAX_H_
#define _MAX_H_
double max(double a,double b);
extern int gAll;
struct Node{
int value;
char* name;
};
#endif
max.c
#include <stdio.h>
#include "max.h"
int gAll = 12;
int main(void) {
double a = 5;
double b = 6;
printf("max is %f\n", max(5, 6)); // max is 6.000000
return 0;
}
max.c
#include "max.h"
double max(double a,double b)
{
return a > b ? a : b;
}