C 語言中的 #ifndef

Jinku Hu 2023年1月30日 2021年2月7日
  1. 在 C 語言中使用 ifndef 保護標頭檔案不被多次包含
  2. 使用 ifndef 指令來確保巨集在 C 語言中不會被多次定義
C 語言中的 #ifndef

本文將演示如何在 C 語言中使用 #ifndef 避免重入包含的多種方法。

在 C 語言中使用 ifndef 保護標頭檔案不被多次包含

C 語言中的標頭檔案用於定義同名原始檔中實現的函式的介面。介面通常包括函式原型、公開訪問的資料結構的定義以及其他一些雜項。

注意,標頭檔案可能會多次包含在原始檔中,導致編譯器出錯。通常情況下,用 #ifndef 前處理器指令可以防止這種情況發生,這個指令叫做包裝器 #ifndef。當標頭檔案的內容被封裝成如下例所示的結構時,其中指令 #ifndef MY_GUARD 是起點,#endif 是終點。ifndef 指令檢查是否定義了 MY_GUARD 巨集,如果沒有則繼續,用下一個指令定義。如果使用者第二次包含相同的頭,ifndef 指令將評估為 false,並忽略 #endif 指令之前的程式碼。因此,編譯器將只從這個標頭檔案中得到一份程式碼,併成功編譯。

#include <stdio.h>

#ifndef MY_GUARD
#define MY_GUARD 1

#define  PER(D) #D
#define  JOIN(A,B) (A ## B)
#define  JOINX(A,B) JOIN(A,B)

int power(int base, int n) {
    int p = base;
    for (size_t i = 0; i < n; i++) {
      p *= base;
    }
    return p;
}
#endif

另一種達到同樣效果的方法是在標頭檔案中包含 #pragma once 指令。前處理器只對這些標頭檔案掃描一次,並保證不被再次讀取。下面的方法有一個缺點,就是它在不同的前處理器之間的可移植性很低,所以大家不妨堅持使用包裝器 #ifndef 方法,以保證程式碼庫有更好的靈活性。

#include <stdio.h>

#pragma once

#define  PER(D) #D
#define  JOIN(A,B) (A ## B)
#define  JOINX(A,B) JOIN(A,B)

int power(int base, int n) {
    int p = base;
    for (size_t i = 0; i < n; i++) {
      p *= base;
    }
    return p;
}

使用 ifndef 指令來確保巨集在 C 語言中不會被多次定義

另外,我們也可以使用 ifndef 指令檢查給定的巨集表示式是否已經被定義。邏輯工作原理和上一個例子完全一樣,如果表示式沒有被定義,下一個 #define 指令就會進行相應的處理。#ifndef#endif 之間只有一行是一個巨集定義,這意味著如果條件為假,只跳過給定的巨集定義。

#include <stdio.h>
#include <stdlib.h>

#define  PER(D) #D

#ifndef DLEVEL
#define DLEVEL 6
#endif

int main() {

    for (int j = 0; j < DLEVEL; ++j) {
        printf("%s\n", PER(stringify this));
    }

    exit(EXIT_SUCCESS);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn