C語言探索之旅 | 第二部分第五課:預(yù)處理

作者 謝恩銘,公眾號「程序員聯(lián)盟」(微信號:coderhub)。
轉(zhuǎn)載請注明出處。
原文:http://www.itdecent.cn/p/cb83bb7e9141

《C語言探索之旅》全系列

內(nèi)容簡介


  1. 前言
  2. include 指令
  3. define 命令
  4. 條件編譯
  5. 總結(jié)
  6. 第二部分第六課預(yù)告

1. 前言


上一課 C語言探索之旅 | 第二部分第四課:字符串 ,我們結(jié)束了關(guān)于字符串的旅程。

大家在一起經(jīng)歷了前三課:指針、數(shù)組和字符串的“疲勞轟炸”之后,這一課回歸輕松。

就像剛在沙漠里行走了數(shù)日,突然看到一片綠洲,還有準(zhǔn)備好的躺椅,清澈的小湖,冷飲,西瓜,一臺頂配電腦(又暴露了程序員的本質(zhì)...)... 腦補(bǔ)一下這個(gè)畫面還是挺開心的。

前面三課我們一下子學(xué)了不少新知識點(diǎn),雖然我沒有那么"善良",但也不至于不給大家小憩的機(jī)會(huì)啊。

這一課我們來聊聊“預(yù)處理器”,這個(gè)程序就在編譯之前運(yùn)行。

當(dāng)然了,雖然這一課不難,可以作為中場休息,但不要認(rèn)為這一課的內(nèi)容不重要。相反,這一課的內(nèi)容非常有用(讀者:“你就說哪一課的內(nèi)容不是非常有用吧...”)。

2. include 指令


在這個(gè)系列教程最初的某一課里,我們已經(jīng)向大家解釋過:在源代碼里面總有那么幾行代碼是很特別的,稱之為預(yù)處理命令。

這些命令的特別之處就在于它們總是以 # 開頭,所以很容易辨認(rèn)。

預(yù)處理命令有好幾種,我們現(xiàn)在只接觸了一種:以 #include 開始的預(yù)處理命令。

#include 命令可以把一個(gè)文件的內(nèi)容包含到另一個(gè)文件中。

在之前的課程里我們已經(jīng)學(xué)習(xí)了如何用 #include 命令來包含頭文件(以 .h 結(jié)尾的)。

頭文件有兩種,一種是 C語言的標(biāo)準(zhǔn)庫定義的頭文件(stdio.h,stdlib.h,等),另一種是用戶自定義的頭文件。

  • 如果要導(dǎo)入 C語言標(biāo)準(zhǔn)庫的頭文件(位于你安裝的 IDE(集成開發(fā)環(huán)境)的文件夾或者編譯器的文件夾里),需要用到尖括號 <>。如下所示:
#include <stdio.h>
  • 如果要導(dǎo)入用戶自己項(xiàng)目中定義的頭文件(位于你自己項(xiàng)目的文件夾里),需要用到雙引號。如下所示:
#include "file.h"

事實(shí)上,預(yù)處理器(preprocessor)在編輯之前運(yùn)行,它會(huì)遍歷你的源文件,尋找每一個(gè)以 # 開頭的預(yù)處理命令。

例如,當(dāng)它遇到 #include 開頭的預(yù)處理命令,就會(huì)把后面跟的頭文件的內(nèi)容插入到此命令處,作為替換。

假設(shè)我有一個(gè) C 文件(就是 .c 文件),包含我的函數(shù)的實(shí)現(xiàn)代碼;還有一個(gè) H 文件(就是 .h 文件),包含函數(shù)的原型。

我們可以用下圖來描繪預(yù)處理的時(shí)候發(fā)生的情況:

如上圖所示,H 文件的所有內(nèi)容都將替換 C 文件的那一行預(yù)處理命令(#include "file.h")。

假設(shè)我們的 C 文件內(nèi)容如下所示:

#include "file.h"

int myFunction(int thing, double stuff)
{
/* 函數(shù)體 */
}

void anotherFunction(int value)
{
/* 函數(shù)體 */
}

我們的 H 文件內(nèi)容如下所示:

int myFunction(int thing, double stuff);
void anotherFunction(int value);

編輯之前,預(yù)處理器就會(huì)用 H 文件的內(nèi)容替換那一行 #include "file.h"。

經(jīng)過替換之后,C 文件內(nèi)容如下:

int myFunction(int thing, double stuff);
void anotherFunction(int value);

int myFunction(int thing, double stuff)
{
/* 函數(shù)體 */
}

void anotherFunction(int value)
{
/* 函數(shù)體 */
}

3. define 命令


現(xiàn)在我們一起來學(xué)習(xí)一個(gè)新的預(yù)處理命令,就是 #define 命令。

define 表示“定義”。

這個(gè)命令使我們可以定義預(yù)處理常量,也就是把一個(gè)值綁定到一個(gè)名稱。例如:

#define LIFE_NUMBER 7

我們必須按照以下順序來寫:

  • #define
  • 要綁定數(shù)值的那個(gè)名稱
  • 數(shù)值

注意:雖然說這里的名稱是大寫字母(因?yàn)榱?xí)慣如此,你也可以小寫),但是這與我們之前學(xué)過的 const 變量還是很不一樣。

const 變量的定義是像這樣的:

const int LIFE_NUMBER = 7;

上面的 const 變量在內(nèi)存中是占用空間的,雖然其不能改變,但是它確確實(shí)實(shí)儲存在內(nèi)存的某個(gè)地方。但是預(yù)處理常量卻不是這樣。

那預(yù)處理常量是怎樣運(yùn)作的呢?

事實(shí)上,預(yù)處理器會(huì)把由 #define 定義的所有的名稱替換成對應(yīng)的值。

如果大家使用過微軟的軟件 Word,那應(yīng)該對“查找并替換”的功能比較熟悉。我們的 #define 就有點(diǎn)類似這個(gè)功能,它會(huì)查找當(dāng)前文件的所有 #define 定義的常量名稱,將其替換為對應(yīng)的數(shù)值。

你也許要問:“用預(yù)處理常量意義何在呢?有什么好處?”

問得好。

  • 第一,因?yàn)轭A(yù)處理常量不用儲存在內(nèi)存里。就如我們之前所說,在編譯之前,預(yù)處理常量都被替換為代碼中的數(shù)值了。

  • 第二,預(yù)處理常量的替換會(huì)發(fā)生在所有引入 #define 語句的文件里。如果我們在一個(gè)函數(shù)里定義一個(gè) const 變量,那么它會(huì)在內(nèi)存里儲存,但是如果前面不加 static 關(guān)鍵字(關(guān)于 static,請參看之前的課程)的話,它只在當(dāng)前函數(shù)有效,函數(shù)執(zhí)行完就被銷毀了。然而預(yù)處理常量卻不是這樣,它可以作用于所有函數(shù),只要函數(shù)里有那個(gè)名稱,都會(huì)替換為對應(yīng)的數(shù)值。這樣的機(jī)制在有些時(shí)候是非常有用的。特別對于嵌入式開發(fā),內(nèi)存比較有限,經(jīng)常能看到預(yù)處理常量的使用。

“能否給出一個(gè)實(shí)際使用 #define 的例子呢?”

當(dāng)然可以。例如,當(dāng)你用 C語言來創(chuàng)建一個(gè)窗口時(shí),你需要定義窗口的寬度和高度,這時(shí)候就可以使用 #define 了:

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

看到使用預(yù)處理常量的好處了么?之后如果你要修改窗口的寬度和高度,不必到代碼里去改每一個(gè)值,只需要在定義處修改就好了,非常節(jié)省時(shí)間。

注意:通常來說,#define 語句放在 .h 頭文件中,和函數(shù)原型那些家伙在一起。
如果有興趣,大家可以去看一下標(biāo)準(zhǔn)庫的 .h 文件,例如 stdio.h,你可以看到有不少 #define 語句。

用于數(shù)組大?。ňS度)的 #define


我們在 C語言編程中也可以使用預(yù)處理常量(#define 語句定義)來定義數(shù)組的大小。例如:

#define MAX_DIMENSION 2000

int main(int argc, char *argv[])
{
    char string1[MAX_DIMENSION], string2[MAX_DIMENSION];
    // ...
}

你也許會(huì)問:“但是,不是說我們不能在數(shù)組的中括號中放變量,甚至是 const 變量也不可以嗎?”

對,但是 MAX_DIMENSION 并不是一個(gè)變量,也不是一個(gè) const 變量??!就如之前說的,預(yù)處理器會(huì)在編譯之前把以上代碼替換為如下:

int main(int argc, char *argv[])
{
    char string1[2000], string2[2000];
    // ...
}

這樣有一個(gè)好處,就如之前所說,如果將來你覺得你的數(shù)組大小要修改,可以直接修改 MAX_DIMENSION 的數(shù)值,非常便捷。

在 #define 中的計(jì)算


我們還可以在定義預(yù)處理常量時(shí)(#define 語句中)做一些計(jì)算。

例如,以下代碼首先定義了兩個(gè)預(yù)處理常量 WINDOW_WIDTH(表示“窗口寬度”)和 WINDOW_HEIGHT(表示“窗口高度”),接著我們可以利用這兩個(gè)預(yù)處理常量來定義第三個(gè)預(yù)處理常量:PIXEL_NUMBER(意思是“像素?cái)?shù)目”,等于“窗口寬度” x “窗口高度”),如下:

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define PIXEL_NUMBER (WINDOW_WIDTH * WINDOW_HEIGHT)

在編譯之前,PIXEL_NUMBER 會(huì)被替換為 800 x 600 = 480000 。

當(dāng)然預(yù)處理常量對于基本的運(yùn)算:+-,*/% 都是支持的。

注意:用 #define 定義預(yù)處理常量時(shí)要盡量多用括號括起來,不然會(huì)出現(xiàn)意想不到的結(jié)果,因?yàn)轭A(yù)處理常量只是簡單的替換。

系統(tǒng)預(yù)先定義好的預(yù)處理常量


我們自己可以定義很多預(yù)處理常量,C語言系統(tǒng)也為我們預(yù)先定義了幾個(gè)有用的預(yù)處理常量。

這些 C語言預(yù)定義的預(yù)處理常量一般都以兩個(gè)下劃線開始,兩個(gè)下劃線結(jié)束,例如:

  • __LINE__ :當(dāng)前行號。
  • __FILE__ :當(dāng)前文件名。
  • __DATE__ :編譯時(shí)的日期。
  • __TIME__ :編譯時(shí)的時(shí)刻。

這些預(yù)處理常量對于標(biāo)明出錯(cuò)的地方和調(diào)試是很有用的,用法如下:

printf("錯(cuò)誤在文件 %s 的第 %d 行\(zhòng)n", __FILE__, __LINE__);
printf("此文件在 %s %s 被編譯\n", __DATE__, __TIME__);

輸出如下:

錯(cuò)誤在文件 main.c 的第 10 行
此文件在 Jun 8 2020 09:11:01 被編譯

不帶數(shù)值的 #define


我們也可以像如下這樣定義預(yù)處理常量:

#define CONSTANT

很奇怪吧,后面竟然沒有對應(yīng)的數(shù)值。

以上語句用于告訴預(yù)處理器:CONSTANT 這個(gè)預(yù)處理常量已經(jīng)定義了,僅此而已。雖然它沒有對應(yīng)的數(shù)值,但是它“存在”。

你也許要問:“這樣有什么意義呢?”

這樣做的用處暫時(shí)還不明顯,但是我們在這一課里馬上會(huì)學(xué)到,請繼續(xù)讀下去。

4. 宏


我們現(xiàn)在知道用 #define 語句可以把一個(gè)數(shù)值綁定到一個(gè)名稱上,然后在預(yù)處理階段(編譯之前)預(yù)處理器就可以在代碼里用數(shù)值替換所有的預(yù)處理常量了,非常方便。例如:

#define NUMBER 10

意味著接下來你的代碼里所有的 NUMBER 都會(huì)被替換為 10。是簡單的“查找-替換”。

但是 #define 預(yù)處理命令還可以做更厲害的事。

#define 還可以用來替換… 一整個(gè)代碼體。當(dāng)我們用 #define 來定義一個(gè)預(yù)處理常量,這個(gè)預(yù)處理常量的值是一段代碼的時(shí)候,我們說我們創(chuàng)建了一個(gè)“宏”。

“宏”,英語是 macro。一開始可能不太好理解。這是一個(gè)編程術(shù)語,臺灣一般翻成“巨集”??梢哉f是一種抽象,但在 C語言里就只用于簡單的“查找-替換”。

趣事:之前某網(wǎng)站出現(xiàn)一個(gè)詞:“王力巨集”,原來這個(gè)網(wǎng)站在做簡體中文到繁體中文轉(zhuǎn)換時(shí),把明星“王力宏”的名字中的“宏”替換為了“巨集”,我們的力宏就這么“躺槍”了…

沒有參數(shù)的宏


下面給出一個(gè)很簡單的宏的定義:

#define HELLO() printf("Hello\n");

可以看到,與之前的預(yù)處理常量不太一樣的是:名稱后多了一對括號,我們馬上就來看這有什么用處。

我們用一段代碼來測試一下:

#include <stdio.h>

#define HELLO() printf("Hello\n");

int main(int argc, char *argv[])
{
    HELLO()

    return 0;
}

運(yùn)行輸出:

Hello

是不是有點(diǎn)意思?不過暫時(shí)還不是那么新穎。

需要理解的是:宏不過是在編譯之前的一些代碼的簡單替換。

上面的代碼在編譯前會(huì)被替換為如下:

int main(int argc, char *argv[])
{
    printf("Hello\n");

    return 0;
}

如果你理解了這個(gè),那對于宏的基本概念也差不多理解了。

你也許會(huì)問:“那我們每一個(gè)宏只能寫在一行上么?”

不是的,只需要在每一行的結(jié)尾寫上一個(gè) \(反斜杠),就可以開始寫新的一行了,而預(yù)處理器會(huì)把這些行看成一行??梢哉f \ 起到了鏈接的作用。例如:

#include <stdio.h>

#define PRESENT_YOURSELF() printf("您好, 我叫 Oscar\n"); \
                           printf("我住在浙江杭州\n"); \
                           printf("我喜歡游泳\n");

int main(int argc, char *argv[])
{
    PRESENT_YOURSELF()

    return 0;
}

運(yùn)行輸出:

您好,我叫 Oscar
我住在浙江杭州
我喜歡游泳

我們注意到了,調(diào)用宏的時(shí)候,在末尾是沒有分號的。事實(shí)上,因?yàn)?/p>

PRESENT_YOURSELF()

這一行是給預(yù)處理器來處理的,所以沒必要以分號結(jié)尾。

有參數(shù)的宏


我們剛學(xué)習(xí)了無參的宏,也就是括號里沒有帶參數(shù)的宏。這樣的宏有一個(gè)好處就是可以使代碼里經(jīng)常出現(xiàn)的較長的代碼段變得短一些,看起來簡潔。

但是,宏帶了參數(shù)才真正變得有趣起來。

#include <stdio.h>

#define MATURE(age) if (age >= 18) \
                    printf("你成年了\n");

int main(int argc, char *argv[])
{
    MATURE(25)

    return 0;
}

運(yùn)行輸出:

你成年了

這樣是不是就有點(diǎn)像函數(shù)了?就是這么酷炫。

上面的宏是怎么運(yùn)作的呢?

age 這個(gè)參數(shù)在實(shí)際調(diào)用宏的時(shí)候,會(huì)被替換為括號里的數(shù)值,這里是 25。所以,整個(gè)宏就替換為了:

if (25 >= 18)
    printf("你成年了\n");

不就是我們熟悉的老朋友:if 語句么。

上面的宏定義中,我們也可以用一個(gè) else 來處理“你還未成年”的條件,自己動(dòng)手試一下吧,不難。

當(dāng)然我們也可以創(chuàng)建帶多個(gè)參數(shù)的宏,例如:

#include <stdio.h>

#define MATURE(age, name) if (age >= 18) \
                          printf("你已經(jīng)成年了,%s\n", name);

int main(int argc, char *argv[])
{
    MATURE(32, "Oscar")

    return 0;
}

運(yùn)行輸出:

你已經(jīng)成年了,Oscar

好了,對于宏我們需要了解的也差不多介紹完了。如果使用得當(dāng),宏是相當(dāng)有用的。

但是有些時(shí)候,濫用宏也會(huì)產(chǎn)生很多難以調(diào)試的錯(cuò)誤,所以宏是 C語言的一把雙刃劍。

通常我們在 C語言的編程中是不需要經(jīng)常使用宏的,因?yàn)楹暧幸粋€(gè)缺點(diǎn):

宏只是簡單的替換,根本不檢查變量和參數(shù)類型,所以用得不好會(huì)出問題。

不過,很多復(fù)雜的庫,例如擅長圖形界面編程的 wxWidgets 和 Qt,就大量使用了宏。

所以對于宏,我們需要理解。

5. 條件編譯


預(yù)處理命令除了有以上三個(gè)作用以外,還可以實(shí)現(xiàn)“條件編譯”。聽起來有點(diǎn)玄乎,但是只要語文沒有還給小學(xué)體育老師,那應(yīng)該不難理解。

開個(gè)玩笑。我們還是一起來看看如下的例子:

#if 條件1
/* 如果條件1為真,將會(huì)被編譯的代碼 */
#elif 條件2
/* 如果條件2為真,將會(huì)被編譯的代碼 */
#endif

是不是有點(diǎn)類似之前學(xué)過的 if 語句?

可以看到:

  • 關(guān)鍵字 #if 是一個(gè)條件編譯塊的起始,在后面可以插入一個(gè)條件。
  • 關(guān)鍵字 #elif(elif 是 else if 的縮寫)的后面可以插入另一個(gè)條件。
  • 關(guān)鍵字 #endif(end 表示“結(jié)束”)是一個(gè)條件編譯塊的結(jié)束。

與 if 語句不同的是,條件編譯沒有大括號。

你會(huì)發(fā)現(xiàn)“條件編譯”是相當(dāng)有用的,它使我們可以按照不同的條件來選擇編譯哪些代碼。

與 if 語句類似,條件編譯塊必須有且只能有一個(gè) #if,可以沒有或有多個(gè) #elif,必須有且只能有一個(gè) #endif。

如果條件為真,那么后面跟著的代碼會(huì)被編譯,如果條件為假,后面的代碼就會(huì)在編譯時(shí)被忽略。

#ifdef 和 #ifndef


現(xiàn)在我們就來看看之前介紹的“沒有數(shù)值的 #define”的用處。

還記得嗎?

#define CONSTANT

我們可以

  • #ifdef 來表述:“如果此名稱已經(jīng)被定義”。因?yàn)?ifdef 是 if defined 的縮寫,表示“如果已被定義”。
  • #ifndef 來表述:“如果此名稱沒有被定義”。因?yàn)?ifndef 是 if not defined 的縮寫,表示“如果沒有被定義”。

不得不重提英語對于編程進(jìn)階的重要性,可以參看我之前寫的文章:對于程序員, 為什么英語比數(shù)學(xué)更重要? 如何學(xué)習(xí)

例如我們有如下代碼:

#define WINDOWS

#ifdef WINDOWS
/* 當(dāng) WINDOWS 已經(jīng)被定義的時(shí)候要編譯的代碼 */
#endif

#ifdef LINUX
/* 當(dāng) LINUX 已經(jīng)被定義的時(shí)候要編譯的代碼 */
#endif

#ifdef MAC
/* 當(dāng) MAC 已經(jīng)被定義的時(shí)候要編譯的代碼 */
#endif

可以看到,用這樣的方法,可以很方便地應(yīng)對不同平臺的編譯,使我們的代碼實(shí)現(xiàn)跨平臺。

比如,我要編譯針對 Windows 系統(tǒng)的代碼,那就在開始處寫:

#define WINDOWS

我要編譯針對 Linux 系統(tǒng)的代碼,那就改成:

#define LINUX

如果是 macOS 系統(tǒng),那就改成:

#define MAC

當(dāng)然了,每次修改代碼之后都要重新編譯(畢竟沒有那么神奇)。

使用 #ifndef 來避免“重復(fù)包含”


#ifndef 是非常有用的,經(jīng)常用于 .h 頭文件中,以避免“重復(fù)包含”。

什么是“重復(fù)包含”呢?

其實(shí)不難理解,設(shè)想以下情況:

我有兩個(gè)頭文件,分別命名為 A.h 和 B.h 。在 A.h 中我寫了

#include "B.h"

而不巧在 B.h 中我寫了

#include "A.h"

要知道,在代碼復(fù)雜度提高以后,這樣的情況不是不可能發(fā)生的。很多時(shí)候,我們一個(gè)文件里要 inculde 好多個(gè)頭文件,很容易暈。

這樣一來,A.h 文件需要 B.h 來運(yùn)行,而 B.h 文件需要 A.h 來運(yùn)行。

如果我們稍加思索,就不難想到會(huì)發(fā)生什么:

  • 電腦讀入 A.h 文件,發(fā)現(xiàn)需要包含 B.h。

  • 電腦在 A.h 中包含進(jìn) B.h 文件的內(nèi)容,可是在 B.h 文件的內(nèi)容里又發(fā)現(xiàn)需要包含 A.h。

  • 如此循環(huán)往復(fù),什么時(shí)候是個(gè)頭啊…

你肯定認(rèn)為這會(huì)永不止息…

事實(shí)上,碰到這種情況,預(yù)處理器會(huì)停止,并且拋出“我受不了這么多包含啦!”的錯(cuò)誤,你的程序就不能通過編譯。

那如何來避免這樣的悲劇呢?

下面就是解方。并且從今以后,我強(qiáng)烈建議大家在每一個(gè) .h 頭文件中都這樣做!讓我任性一回吧...

#ifndef DEF_FILENAME  // 如果此預(yù)處理常量還未被定義,即是說這個(gè)文件未被包含過
#define DEF_FILENAME  // 定義此預(yù)處理常量,以避免重復(fù)包含

/* file.h 文件的內(nèi)容 (其他的 #include,函數(shù)原型,#define,等...) */

#endif

如上所示,在 #ifndef#endif 之間我們放置 .h 文件的內(nèi)容(其他的 #include,函數(shù)原型,#define,等)。

我們來理解一下到底這段代碼是怎么起作用的?(我自己第一次碰到這個(gè)技術(shù)時(shí)也有點(diǎn)不太理解):

假使我們的 file.h 文件是第一次被包含(被 include),預(yù)處理器讀到開頭的那句話:

#ifndef DEF_FILENAME

意思是“DEF_FILENAME 這個(gè)預(yù)處理常量還沒有被定義”,這個(gè)條件是真的。所以預(yù)處理器就進(jìn)入 #if 語句內(nèi)部啦(和普通的 if 語句類似的機(jī)制)。

接著預(yù)處理器就讀到第二句命令:

#define DEF_FILENAME

這句的意思是“定義 DEF_FILENAME 這個(gè)預(yù)處理常量”。所以預(yù)處理器乖乖地執(zhí)行,定義 DEF_FILENAME。

接著它就將 file.h 頭文件的主體內(nèi)容都包含進(jìn)調(diào)用 #include "file.h" 或者 #include <file.h> 的那個(gè)文件。

這樣的話。下一次這個(gè) file.h 頭文件再被其他文件包含時(shí),`

#ifndef DEF_FILENAME

這個(gè)條件就不為真了,預(yù)處理器就不會(huì)執(zhí)行條件編譯內(nèi)部的語句了,自然就不會(huì)再把頭文件的主體內(nèi)容包含了。

這樣就能巧妙地避免“重復(fù)包含”。

當(dāng)然,那個(gè)預(yù)處理常量的名稱不一定要和我的一樣,也不一定要大寫,但是最好大寫,是約定俗成的用法。

但是每一個(gè)頭文件的所用常量名稱必須不同,否則,只有第一個(gè)頭文件會(huì)被包含。

非常建議大家有空去看一下標(biāo)準(zhǔn)庫的頭文件,如 stdio.h,stdlib.h,等。你會(huì)發(fā)現(xiàn)它們都是以這樣的方式寫的(開頭 #ifndef,結(jié)尾 #endif)。

6. 總結(jié)


  1. 預(yù)處理器是這樣一個(gè)程序,它在編譯之前執(zhí)行,它先分析源代碼,然后做出一定修改。

  2. 預(yù)處理命令有好幾種。#include 命令用于在一個(gè)文件中插入另一個(gè)文件的內(nèi)容。

  3. #define 命令定義一個(gè)預(yù)處理常量。之后預(yù)處理器就會(huì)把代碼里所有 #define 定義的常量名稱替換成對應(yīng)的值。

  4. 宏是一些代碼塊,定義也要借助 #define。宏可以接受參數(shù)。

  5. 我們也可以用預(yù)處理器的語言來寫一些預(yù)處理?xiàng)l件,以實(shí)現(xiàn)條件編譯。一般我們使用關(guān)鍵字:#if,#elif#endif 等。

  6. 為了防止一個(gè)頭文件被多次包含,我們會(huì)用條件編譯和預(yù)處理常量的組合來“保護(hù)”它。之后我們寫的 .h 頭文件都會(huì)采用這種方式,也很建議采用。

7. 第二部分第六課預(yù)告


今天的課就到這里,一起加油吧!

下一課:C語言探索之旅 | 第二部分第六課:創(chuàng)建你自己的變量類型


我是 謝恩銘,公眾號「程序員聯(lián)盟」(微信號:coderhub)運(yùn)營者,慕課網(wǎng)精英講師 Oscar 老師,終生學(xué)習(xí)者。
熱愛生活,喜歡游泳,略懂烹飪。
人生格言:「向著標(biāo)桿直跑」

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容