1. 程式人生 > >6.3 大程式結構

6.3 大程式結構

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;
}