• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
                                                              預(yù)處理過程

            預(yù)處理過程掃描源代碼,對其進行初步的轉(zhuǎn)換,產(chǎn)生新的源代碼提供給編譯器。可見預(yù)處理過程先于編譯器對源代碼進行處理。
            C語言中,并沒有任何內(nèi)在的機制來完成如下一些功能:在編譯時包含其他源文件、定義宏、根據(jù)條件決定編譯時是否包含某些代碼。要完成這些工作,就需要使用預(yù)處理程序。盡管在目前絕大多數(shù)編譯器都包含了預(yù)處理程序,但通常認(rèn)為它們是獨立于編譯器的。預(yù)處理過程讀入源代碼,檢查包含預(yù)處理指令的語句和宏定義,并對源代碼進行響應(yīng)的轉(zhuǎn)換。預(yù)處理過程還會刪除程序中的注釋和多余的空白字符。
            預(yù)處理指令是以#號開頭的代碼行。#號必須是該行除了任何空白字符外的第一個字符。#后是指令關(guān)鍵字,在關(guān)鍵字和#號之間允許存在任意個數(shù)的空白字符。整行語句構(gòu)成了一條預(yù)處理指令,該指令將在編譯器進行編譯之前對源代碼做某些轉(zhuǎn)換。下面是部分預(yù)處理指令:

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

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

                    #define AAA
                    #include "t.c"
                    #undef AAA
                    #include "t.c"

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

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

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

                        #define PASTE(n) "adhfkj"#n

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

                        #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
                    
            千萬別擔(dān)心,除非需要或者宏的用法恰好和手頭的工作相關(guān),否則很少有程序員會知道##運算符。絕大多數(shù)程序員從來沒用過它。

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

                        #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指令之后,當(dāng)前面的#if指令的條件不為真時,就編譯#else后面的代碼。#endif指令將中指上面的條件塊。

                    #define DEBUG

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

                5.#elif
            指令
                    #elif
            預(yù)處理指令綜合了#else#if指令的作用。

                    #define TWO

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

                6.
            其他一些標(biāo)準(zhǔn)指令
                    #error
            指令將使編譯器顯示一條錯誤信息,然后停止編譯。
                    #line
            指令可以改變編譯器用來指出警告和錯誤信息的文件號和行號。
                    #pragma
            指令沒有正式的定義。編譯器可以自定義其用途。典型的用法是禁止或允許某些煩人的警告信息。
            Posted on 2005-11-03 11:30 艾凡赫 閱讀(495) 評論(0)  編輯 收藏 引用 所屬分類: 基礎(chǔ)知識
            大蕉久久伊人中文字幕| 国产精自产拍久久久久久蜜| 亚洲精品无码久久久| 久久99精品国产麻豆婷婷| 久久丝袜精品中文字幕| 国产成人久久精品一区二区三区 | 青草国产精品久久久久久| 久久久久久午夜成人影院| 久久精品国产精品亜洲毛片| 99精品国产免费久久久久久下载| 东方aⅴ免费观看久久av| 韩国无遮挡三级久久| 久久人做人爽一区二区三区| 九九99精品久久久久久| 久久亚洲中文字幕精品一区| 99久久夜色精品国产网站| 午夜天堂av天堂久久久| 久久精品国产第一区二区| 国产成人综合久久综合| 狠狠综合久久AV一区二区三区| 欧美亚洲另类久久综合婷婷| 精品精品国产自在久久高清| 97久久国产露脸精品国产| 久久亚洲AV无码精品色午夜| 精品国产婷婷久久久| 伊人丁香狠狠色综合久久| 久久久久人妻精品一区| 97精品依人久久久大香线蕉97| 思思久久99热只有频精品66| 国产精品九九久久免费视频 | 日韩精品无码久久一区二区三| 91视频国产91久久久| 久久国产精品一国产精品金尊| 国产亚洲美女精品久久久2020| 久久夜色精品国产亚洲| 久久精品国产99久久久古代| 久久青青草视频| 国产成人久久精品一区二区三区| 久久亚洲AV成人无码软件| 久久精品一区二区三区AV| 久久九九久精品国产免费直播|