程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> C語言條件編譯詳解

C語言條件編譯詳解

編輯:C語言基礎知識
假如現在要開發一個C語言程序,讓它輸出紅色的文字,並且要求跨平台,在 Windows 和 Linux 下都能運行,怎麼辦呢?

這個程序的難點在於,不同平台下控制文字顏色的代碼不一樣,我們必須要能夠識別出不同的平台。

Windows 有專有的宏_WIN32,Linux 有專有的宏__linux__,以現有的知識,我們很容易就想到了 if else,請看下面的代碼:
#include <stdio.h>
int main(){
    if(_WIN32){
        system("color 0c");
        printf("http://c.biancheng.net\n");
    }else if(__linux__){
        printf("\033[22;31mhttp://c.biancheng.net\n\033[22;30m");
    }else{
        printf("http://c.biancheng.net\n");
    }

    return 0;
}
但這段代碼是錯誤的,在 Windows 下提示 __linux__ 是未定義的標識符,在 Linux 下提示 _Win32 是未定義的標識符。對上面的代碼進行改進:
#include <stdio.h>
int main(){
    #if _WIN32
        system("color 0c");
        printf("http://c.biancheng.net\n");
    #elif __linux__
        printf("\033[22;31mhttp://c.biancheng.net\n\033[22;30m");
    #else
        printf("http://c.biancheng.net\n");
    #endif

    return 0;
}
#if、#elif、#else 和 #endif 都是預處理命令,整段代碼的意思是:如果宏 _WIN32 的值為真,就保留第 4、5 行代碼,刪除第 7、9 行代碼;如果宏 __linux__ 的值為真,就保留第 7 行代碼;如果所有的宏都為假,就保留第 9 行代碼。

這些操作都是在預處理階段完成的,多余的代碼以及所有的宏都不會參與編譯,不僅保證了代碼的正確性,還減小了編譯後文件的體積。

這種能夠根據不同情況編譯不同代碼、產生不同目標文件的機制,稱為條件編譯。條件編譯是預處理程序的功能,不是編譯器的功能。

條件編譯有多種形式,下面一一講解。

#if 命令

#if 命令的完整格式為:

#if 整型常量表達式1
    程序段1
#elif 整型常量表達式2
    程序段2
#elif 整型常量表達式3
    程序段3
#else
    程序段4
#endif

它的意思是:如常“表達式1”的值為真(非0),就對“程序段1”進行編譯,否則就計算“表達式2”,結果為真的話就對“程序段2”進行編譯,為假的話就繼續往下匹配,直到遇到值為真的表達式,或者遇到 #else。這一點和 if else 非常類似。

需要注意的是,#if 命令要求判斷條件為“整型常量表達式”,也就是說,表達式中不能包含變量,而且結果必須是整數;而 if 後面的表達式沒有限制,只要符合語法就行。這是 #if 和 if 的一個重要區別。

#elif 和 #else 也可以省略,如下所示:
#include <stdio.h>
int main(){
    #if _WIN32
        printf("This is Windows!\n");
    #else
        printf("Unknown platform!\n");
    #endif
   
    #if __linux__
        printf("This is Linux!\n");
    #endif

    return 0;
}

#ifdef 命令

#ifdef 命令的格式為:

#ifdef  宏名
    程序段1
#else
    程序段2
#endif

它的意思是,如果當前的宏已被定義過,則對“程序段1”進行編譯,否則對“程序段2”進行編譯。

也可以省略 #else:

#ifdef  宏名
    程序段
#endif


VS/VC 有兩種編譯模式,Debug 和 Release。在學習過程中,我們通常使用 Debug 模式,這樣便於程序的調試;而最終發布的程序,要使用 Release 模式,這樣編譯器會進行很多優化,提高程序運行效率,刪除冗余信息。

為了能夠清楚地看到當前程序的編譯模式,我們不妨在程序中增加提示,請看下面的代碼:
#include <stdio.h>
#include <stdlib.h>
int main(){
    #ifdef _DEBUG
        printf("正在使用 Debug 模式編譯程序...\n");
    #else
        printf("正在使用 Release 模式編譯程序...\n");
    #endif

    system("pause");
    return 0;
}
當以 Debug 模式編譯程序時,宏 _DEBUG 會被定義,預處器會保留第 5 行代碼,刪除第 7 行代碼。反之會刪除第 5 行,保留第 7 行。

#ifndef 命令

#ifndef 命令的格式為:

#ifndef 宏名
    程序段1 
#else 
    程序段2 
#endif

與 #ifdef 相比,僅僅是將 #ifdef 改為了 #ifndef。它的意思是,如果當前的宏未被定義,則對“程序段1”進行編譯,否則對“程序段2”進行編譯,這與 #ifdef 的功能正好相反。

區別

最後需要注意的是,#if 後面跟的是“整型常量表達式”,而 #ifdef 和 #ifndef 後面跟的只能是一個宏名,不能是其他的。

例如,下面的形式只能用於 #if:
#include <stdio.h>
#define NUM 10
int main(){
    #if NUM == 10 || NUM == 20
        printf("NUM: %d\n", NUM);
    #else
        printf("NUM Error\n");
    #endif
    return 0;
}
運行結果:
NUM: 10

再如,兩個宏都存在時編譯代碼A,否則編譯代碼B:
#include <stdio.h>
#define NUM1 10
#define NUM2 20
int main(){
    #if (defined NUM1 && defined NUM2)
        //代碼A
        printf("NUM1: %d, NUM2: %d\n", NUM1, NUM2);
    #else
        //代碼B
        printf("Error\n");
    #endif
    return 0;
}
運行結果:
NUM1: 10, NUM2: 20

#ifdef 可以認為是 #if defined 的縮寫。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved