1. 程式人生 > 其它 >C語言預處理命令是什麼?

C語言預處理命令是什麼?

前面各章中,已經多次使用過#include命令。使用庫函式之前,應該用#include引入對應的標頭檔案。這種以#號開頭的命令稱為預處理命令。

C語言原始檔要經過編譯、連結才能生成可執行程式:

  • 編譯(Compile)會將原始檔(.c檔案)轉換為目標檔案。對於 VC/VS,目標檔案字尾為.obj;對於GCC,目標檔案字尾為.o
編譯是針對單個原始檔的,一次編譯操作只能編譯一個原始檔,如果程式中有多個原始檔,就需要多次編譯操作。
  •  連結(Link)是針對多個檔案的,它會將編譯生成的多個目標檔案以及系統中的庫、元件等合併成一個可執行程式。

關於編譯和連結的過程、目標檔案和可執行檔案的結構、.h 檔案和 .c 檔案的區別,我們將在《C語言多檔案程式設計》專題中講解。

在實際開發中,有時候在編譯之前還需要對原始檔進行簡單的處理。例如,我們希望自己的程式在 Windows 和 Linux 下都能夠執行,那麼就要在 Windows 下使用 VS 編譯一遍,然後在 Linux 下使用 GCC 編譯一遍。但是現在有個問題,程式中要實現的某個功能在 VS 和 GCC 下使用的函式不同(假設 VS 下使用 a(),GCC 下使用 b()),VS 下的函式在 GCC 下不能編譯通過,GCC 下的函式在 VS 下也不能編譯通過,怎麼辦呢?

這就需要在編譯之前先對原始檔進行處理:如果檢測到是 VS,就保留 a() 刪除 b();如果檢測到是 GCC,就保留 b() 刪除 a()。

這些在編譯之前對原始檔進行簡單加工的過程,就稱為預處理(即預先處理、提前處理)。

預處理主要是處理以#開頭的命令,例如#include <stdio.h>等。預處理命令要放在所有函式之外,而且一般都放在原始檔的前面。

預處理是C語言的一個重要功能,由預處理程式完成。當對一個原始檔進行編譯時,系統將自動呼叫預處理程式對源程式中的預處理部分作處理,處理完畢自動進入對源程式的編譯。

編譯器會將預處理的結果儲存到和原始檔同名的.i檔案中,例如 main.c 的預處理結果在 main.i 中。和.c一樣,.i也是文字檔案,可以用編輯器開啟直接檢視內容。

C語言提供了多種預處理功能,如巨集定義、檔案包含、條件編譯等,合理地使用它們會使編寫的程式便於閱讀、修改、移植和除錯,也有利於模組化程式設計。

例項

下面我們舉個例子來說明預處理命令的實際用途。假如現在要開發一個C語言程式,讓它暫停 5 秒以後再輸出內容,並且要求跨平臺,在 Windows 和 Linux 下都能執行,怎麼辦呢?

這個程式的難點在於,不同平臺下的暫停函式和標頭檔案都不一樣:

  • Windows 平臺下的暫停函式的原型是void Sleep(DWORD dwMilliseconds)(注意 S 是大寫的),引數的單位是“毫秒”,位於 <windows.h> 標頭檔案。
  • Linux 平臺下暫停函式的原型是unsigned int sleep (unsigned int seconds),引數的單位是“秒”,位於 <unistd.h> 標頭檔案。

不同的平臺下必須呼叫不同的函式,並引入不同的標頭檔案,否則就會導致編譯錯誤,因為 Windows 平臺下沒有 sleep() 函式,也沒有 <unistd.h> 標頭檔案,反之亦然。這就要求我們在編譯之前,也就是預處理階段來解決這個問題。請看下面的程式碼:

#include <stdio.h>

//不同的平臺下引入不同的標頭檔案
#if _WIN32  //識別windows平臺
#include <windows.h>
#elif __linux__  //識別linux平臺
#include <unistd.h>
#endif

int main() {
    //不同的平臺下呼叫不同的函式
    #if _WIN32  //識別windows平臺
    Sleep(5000);
    #elif __linux__  //識別linux平臺
    sleep(5);
    #endif

    puts("http://www.cdsy.xyz/");

    return 0;
}

#if、#elif、#endif 就是預處理命令,它們都是在編譯之前由預處理程式來執行的。這裡我們不討論細節,只從整體上來理解。

對於 Windows 平臺,預處理以後的程式碼變成:

#include <stdio.h>
#include <windows.h>

int main() {
    Sleep(5000);
    puts("http://www.cdsy.xyz/");

    return 0;
}

對於 Linux 平臺,預處理以後的程式碼變成:

#include <stdio.h>
#include <unistd.h>

int main() {
    sleep(5);
    puts("http://www.cdsy.xyz/");

    return 0;
}

你看,在不同的平臺下,編譯之前(預處理之後)的原始碼都是不一樣的。這就是預處理階段的工作,它把程式碼當成普通文字,根據設定的條件進行一些簡單的文字替換,將替換以後的結果再交給編譯器處理。