<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jasmine214--love

    只有當你的內心總是充滿快樂、美好的愿望和寧靜時,你才能擁有強壯的體魄和明朗、快樂或者寧靜的面容。
    posts - 731, comments - 60, trackbacks - 0, articles - 0

    C語言-宏條件編譯詳解

    Posted on 2012-07-16 15:46 幻海藍夢 閱讀(4336) 評論(0)  編輯  收藏 所屬分類: C語言學習
    處理過程掃描源代碼,對其進行初步的轉換,產生新的源代碼提供給編譯器。可見預處理過程先于編譯器對源代碼進行處理。
    在C 語言中,并沒有任何內在的機制來完成如下一些功能:在編譯時包含其他源文件、定義宏、根據條件決定編譯時是否包含某些代碼。要完成這些工作,就需要使用預 處理程序。盡管在目前絕大多數編譯器都包含了預處理程序,但通常認為它們是獨立于編譯器的。預處理過程讀入源代碼,檢查包含預處理指令的語句和宏定義,并 對源代碼進行響應的轉換。預處理過程還會刪除程序中的注釋和多余的空白字符。
    預處理指令是以#號開頭的代碼行。#號必須是該行除了任何空白字符外的第一個字符。#后是指令關鍵字,在關鍵字和#號之間允許存在任意個數的空白字符。整行語句構成了一條預處理指令,該指令將在編譯器進行編譯之前對源代碼做某些轉換。下面是部分預處理指令:

            指令             用途
                      空指令,無任何效果
             #i nclude    包含一個源代碼文件
             #define     定義宏
             #undef      取消已定義的宏
             #if         如果給定條件為真,則編譯下面代碼
             #ifdef      如果宏已經定義,則編譯下面代碼
             #ifndef     如果宏沒有定義,則編譯下面代碼
             #elif       如果前面的#if給定條件不為真,當前條件為真,則編譯下面代碼
             #endif      結束一個#if……#else條件編譯塊
             #error      停止編譯并顯示錯誤信息

    一、文件包含
        #i nclude預處理指令的作用是在指令處展開被包含的文件。包含可以是多重的,也就是說一個被包含的文件中還可以包含其他文件。標準C編譯器至少支持八重嵌套包含。
        預處理過程不檢查在轉換單元中是否已經包含了某個文件并阻止對它的多次包含。這樣就可以在多次包含同一個頭文件時,通過給定編譯時的條件來達到不同的效果。例如:

            #define AAA
            #i nclude "t.c"
            #undef AAA
            #i nclude "t.c"

        為了避免那些只能包含一次的頭文件被多次包含,可以在頭文件中用編譯時條件來進行控制。例如:
           
            #ifndef MY_H
            #define MY_H
              ……
            #endif

        在程序中包含頭文件有兩種格式:
            #i nclude <my.h>
            #i nclude "my.h"
         第一種方法是用尖括號把頭文件括起來。這種格式告訴預處理程序在編譯器自帶的或外部庫的頭文件中搜索被包含的頭文件。第二種方法是用雙引號把頭文件括起 來。這種格式告訴預處理程序在當前被編譯的應用程序的源代碼文件中搜索被包含的頭文件,如果找不到,再搜索編譯器自帶的頭文件。
        采用兩種不同包含格式的理由在于,編譯器是安裝在公共子目錄下的,而被編譯的應用程序是在它們自己的私有子目錄下的。一個應用程序既包含編譯器提供的公共頭文件,也包含自定義的私有頭文件。采用兩種不同的包含格式使得編譯器能夠在很多頭文件中區別出一組公共的頭文件。

    二、宏
        宏定義了一個代表特定內容的標識符。預處理過程會把源代碼中出現的宏標識符替換成宏定義時的值。宏最常見的用法是定義代表某個值的全局符號。宏的第二種用 法是定義帶參數的宏,這樣的宏可以象函數一樣被調用,但它是在調用語句處展開宏,并用調用時的實際參數來代替定義中的形式參數。
        1.#define指令
            #define預處理指令是用來定義宏的。該指令最簡單的格式是:首先神明一個標識符,然后給出這個標識符代表的代碼。在后面的源代碼中,就用這些代碼來替代該標識符。這種宏把程序中要用到的一些全局值提取出來,賦給一些記憶標識符。
                #define MAX_NUM 10
                int array[MAX_NUM];
                for(i=0;i<MAX_NUM;i++) 
           
             在這個例子中,對于閱讀該程序的人來說,符號MAX_NUM就有特定的含義,它代表的值給出了數組所能容納的最大元素數目。程序中可以多次使用這個值。作 為一種約定,習慣上總是全部用大寫字母來定義宏,這樣易于把程序紅的宏標識符和一般變量標識符區別開來。如果想要改變數組的大小,只需要更改宏定義并重新 編譯程序即可。
            宏表示的值可以是一個常量表達式,其中允許包括前面已經定義的宏標識符。例如:
                #define ONE 1
                #define TWO 2
                #define THREE (ONE+TWO)
            注意上面的宏定義使用了括號。盡管它們并不是必須的。但出于謹慎考慮,還是應該加上括號的。例如:
                six=THREE*TWO;
            預處理過程把上面的一行代碼轉換成:
                six=(ONE+TWO)*TWO;
            如果沒有那個括號,就轉換成six=ONE+TWO*TWO;了。
            宏還可以代表一個字符串常量,例如:
                #define VERSION "Version 1.0 Copyright(c) 2003"
        2.帶參數的#define指令
            帶參數的宏和函數調用看起來有些相似。看一個例子:
                #define Cube(x) (x)*(x)*(x)
            可以時任何數字表達式甚至函數調用來代替參數x。這里再次提醒大家注意括號的使用。宏展開后完全包含在一對括號中,而且參數也包含在括號中,這樣就保證了宏和參數的完整性。看一個用法:
                int num=8+2;
                volume=Cube(num);
            展開后為(8+2)*(8+2)*(8+2);
            如果沒有那些括號就變為8+2*8+2*8+2了。
            下面的用法是不安全的:
                volume=Cube(num++);
            如果Cube是一個函數,上面的寫法是可以理解的。但是,因為Cube是一個宏,所以會產生副作用。這里的擦書不是簡單的表達式,它們將產生意想不到的結果。它們展開后是這樣的:
                volume=(num++)*(num++)*(num++);
            很顯然,結果是10*11*12,而不是10*10*10;
            那么怎樣安全的使用Cube宏呢?必須把可能產生副作用的操作移到宏調用的外面進行:
                int num=8+2;
                volume=Cube(num);
                num++;
        3.#運算符
            出現在宏定義中的#運算符把跟在其后的參數轉換成一個字符串。有時把這種用法的#稱為字符串化運算符。例如:

                #define PASTE(n) "adhfkj"#n

                main()
                {
                   printf("%s/n",PASTE(15));
                }
            宏定義中的#運算符告訴預處理程序,把源代碼中任何傳遞給該宏的參數轉換成一個字符串。所以輸出應該是adhfkj15。
        4.##運算符
            ##運算符用于把參數連接到一起。預處理程序把出現在##兩側的參數合并成一個符號。看下面的例子:

                #define NUM(a,b,c) a##b##c
                #define STR(a,b,c) a##b##c

                main()
                {
                    printf("%d/n",NUM(1,2,3));
                    printf("%s/n",STR("aa","bb","cc"));
                }

            最后程序的輸出為:
                     123
                     aabbcc
            千萬別擔心,除非需要或者宏的用法恰好和手頭的工作相關,否則很少有程序員會知道##運算符。絕大多數程序員從來沒用過它。

    三、條件編譯指令
        條件編譯指令將決定那些代碼被編譯,而哪些是不被編譯的。可以根據表達式的值或者某個特定的宏是否被定義來確定編譯條件。
        1.#if指令
            #if指令檢測跟在制造另關鍵字后的常量表達式。如果表達式為真,則編譯后面的代碼,知道出現#else、#elif或#endif為止;否則就不編譯。
        2.#endif指令
            #endif用于終止#if預處理指令。

                #define DEBUG 0
                main()
                {
                    #if DEBUG
                        printf("Debugging/n");
                    #endif
                        printf("Running/n");
                }

            由于程序定義DEBUG宏代表0,所以#if條件為假,不編譯后面的代碼直到#endif,所以程序直接輸出Running。
            如果去掉#define語句,效果是一樣的。
        3.#ifdef和#ifndef
            #define DEBUG

            main()
            {
                #ifdef DEBUG
                    printf("yes/n");
                #endif
                #ifndef DEBUG
                    printf("no/n");
                #endif
            }
            #if defined等價于#ifdef; #if !defined等價于#ifndef
        4.#else指令
            #else指令用于某個#if指令之后,當前面的#if指令的條件不為真時,就編譯#else后面的代碼。#endif指令將中指上面的條件塊。

            #define DEBUG

            main()
            {
                #ifdef DEBUG
                    printf("Debugging/n");
                #else
                    printf("Not debugging/n");
                #endif
                    printf("Running/n");
           }

        5.#elif指令
            #elif預處理指令綜合了#else和#if指令的作用。

            #define TWO

            main()
            {
                #ifdef ONE
                    printf("1/n");
                #elif defined TWO
                    printf("2/n");
                #else
                    printf("3/n");
                #endif
            }
            程序很好理解,最后輸出結果是2。

        6.其他一些標準指令
            #error指令將使編譯器顯示一條錯誤信息,然后停止編譯。
            #line指令可以改變編譯器用來指出警告和錯誤信息的文件號和行號。
            #pragma指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告信息。

    轉:
    http://blog.chinaunix.net/space.php?uid=20693685&do=blog&id=1892557
    主站蜘蛛池模板: 猫咪免费人成网站在线观看入口 | 亚洲乱理伦片在线观看中字| 亚洲综合小说久久另类区| 亚洲乱码日产精品BD在线观看| 亚洲国产成人无码av在线播放| 99ee6热久久免费精品6| 最新仑乱免费视频| 亚洲A丁香五香天堂网| 久久噜噜噜久久亚洲va久| 久久精品国产亚洲AV久| 一区二区三区在线免费观看视频| 久久精品免费观看| 国产精品美女自在线观看免费| 亚洲精品tv久久久久久久久| 亚洲精品国产情侣av在线| 亚洲精品在线免费观看视频| 吃奶摸下高潮60分钟免费视频| 亚洲国产综合人成综合网站00| 久久久WWW成人免费精品| 青娱乐免费在线视频| 亚洲熟女一区二区三区| 激情无码亚洲一区二区三区| 一区二区三区福利视频免费观看| 亚洲精品视频免费| 亚洲AV无码无限在线观看不卡| 中文字幕av免费专区| 国产免费牲交视频| 亚洲第一区二区快射影院| 国产极品粉嫩泬免费观看| av成人免费电影| 免费又黄又爽的视频| 成人性做爰aaa片免费看| 亚洲中文字幕无码专区| 精品国产亚洲一区二区三区在线观看| 一本色道久久88亚洲综合| 亚洲综合在线一区二区三区 | 国国内清清草原免费视频99| 国产成人精品日本亚洲语音| 亚洲精品无码久久久久| 无人影院手机版在线观看免费| 亚洲另类小说图片|