C語言預先處理、結構體和make的使用–C語言預先處理命令

來源:互聯網
上載者:User

  在C語言程式中加入一些編譯預先處理命令可以提高編程效率,回憶編譯速度。預先處理命令是在編譯來源程式前先對來源程式進行處理,例如,在程式中使用“#defineMAX 256“這條命令定義一個符號常量MAX,則在預先處理時將程式中出現的所有MAX替換為256。預先處理完成後,編譯器(如gcc)開始編譯來源程式以產生可執行代碼。需要注意的是,預先處理命令並不是C語言的一部分,因此每條編譯預先處理命令不需要以分號來結束。

    一、宏定義

    C語言標準允許在程式中用一個標識符來表示一個字串,稱為宏。標識符稱為宏名。在編譯預先處理時,將程式中所有的宏名用相應的字串來替換,這個過程稱為宏替換。宏分為兩種:無參數的宏和有參數的宏。

    1、無參數宏

    無參數宏定義的一般形式為:

#define 標識符 字串

    “#”代表本行是編譯預先處理命令。define是宏定義的關鍵詞,標識符是宏名。字串是宏名所代替的內容,可以是常數、運算式等。

     注意:宏定義和其他編譯預先處理命令不是以分號結尾的。

    例5-1 下面是一個使用無參數宏的程式

#include <stdio.h>

#define PI 3.1415926

 

int main()

{

int r = 100;

double length = 2*PI*r;

printf("The circumference is %f\n",length);

return 0;

}

程式說明:(1)本程式使用PI來代表3.1415926。宏替換是在程式中用相應的字串來替換害名,編譯器預先處理程式對它不作任何檢查。如果有錯誤,只能在編譯器時才會被編譯器發現。(2)習慣上,宏名都用大寫字母。當然也可以用小寫字母。(3)使用宏代替一個字串,可以減少程式中重複書寫某些字串的工作量。可以用一個有意義的宏句來代表無規律的字串,提高程式的可讀性,同時修改起來也方便。如果要把程式中的PI值改為3.14,則只要修改#define這一行即可。如果沒有使用宏,那麼就要尋找程式並修改所有的PI值。(4)宏的作用範圍是從宏定義開始到本來源程式檔案結束為止。也可以使用#undef來提前終止作用範圍。例如:

#define MAX 256

int main()

{

    ...

}

#undef MAX

int f()

{

    ...

}

    由於使用了#undef,使宏名MAX只在main函數中有效。(5)宏定義允許嵌套。例如:

#define MIN 128

#define MAX MIN*2

定義MAX宏時使用了前面已經定義的MIN。

    2、有參數宏

    有參數宏的宏類似於有參數的函數,其定義的一般形式為:

#define 標識符(形參表) 字串

    如果有多個形參,像函數參數一樣以逗號隔開。在程式中使用有參數宏的形式是:

標識符(實參表)

    例5-2示範了有參數宏的實現方法。

#include <stdio.h>

#define MAX(x,y) (x>y?x:y)

 

int main()

{

int a = 5,b = 10,max;

 

max = MAX(5,10);

printf("The max between(%d,%d) is %d\n",a,b,max);

return 0;

}

程式說明:經過編譯預先處理max = MAX(a,b)就替換max=(a>b?a:b)。

    程式第二行的宏定義中運算式x>y?x:y兩邊的括弧不是必需的,但出於良好的編程規範應該加上。如果沒有括弧往往會導致一些意想不到的問題。比如有一個宏定義:

#defineMUL(x,y) x*y

    在程式中有:

int a=5,b=10,c;

c=MUL(a+1,b+1);

    那麼進行宏替換,a+1是x的實參,b+1是y的實參,替換後的結果為:

c=a+1*b+1;

    顯然這是不符合要求的。應該按照如下方式進行宏定義:

#define MUL(x,y) (x)*(y)

    此時宏展開後:

c = (a+1)*(b+1);

    定義有參數的宏時,應該注意:

    宏名與形參表的圓括弧之間不能有空格,否則會導致錯誤。例如:#defineMUL(x,y) (x)*(y),MUL與“(”之間不能有空格。

    宏定義中,字串內的形式參數最好用括弧括起來,以避免錯誤。例如上面的形參都用括弧括起來。

    帶參數的宏與函數的比較:

    有參數宏的形式參數不是變數,不分配記憶體空間,無需說明資料類型。而函數的形參是變數,要分配記憶體空間,在函數定義時要指明參數的資料類型。

    預先處理程式認為有參數宏的是字串,並用它去替換形參。如上面的例子中,用a+1去替換x,而不是先計算a+1的值再去替換x。如果是函數,則先計算a+1的值,再把這個值傳遞給x。

    使用宏的次數較多時,宏替換後來源程式一般會變長。而函數調用不會使程式變長。宏替換不會佔用已耗用時間,只是編譯的時間稍微變長一點。而函數調用則會佔用已耗用時間。一般用宏來代表一些較為簡單的運算式比較合適。

    二、檔案包含

    檔案包含預先處理命令#include前面已經使用過了。它把指定源檔案的全部內容包括到當前來源程式檔案中,其一般形式為:

#include <檔案名稱>

或者

#include "檔案名稱”

    檔案包含命令是把指定檔案的全部內容包括進來,插入到命令所在位置,取代原來的命令列。由當前源檔案和指定檔案組成一個檔案,一起進行編譯。

    一個#include只能包含一個檔案,要包含多個檔案,需要使用多個#include命令。例如:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

    一個大的程式往往被分成多個模組,由多個程式員分別編寫。公用的資訊,如常量定義、函式宣告,可以單獨放在一個檔案中,在其他檔案的開頭使用#include命令包含進來。這樣可以避免每個檔案頭部都去書寫那些公用量,既節省了時間又可以防止出錯的可能。

    檔案包含命令中的檔案名稱既可以用角括弧也可以用雙引號括起來,它們的區別在於尋找指定檔案的位置不同。角括弧只在預設目錄裡找指定檔案,預設目錄是由使用者佈建的編程環境決定的。雙引號則先在來源程式檔案所在的目前的目錄裡尋找指定檔案,如果沒有找到再到預設目錄裡找。如果指定檔案與當前編寫中的來源程式處在同一個目錄裡,就必須使用雙引號來包含該檔案,否則編譯器時編譯器會報告找不到指定的標頭檔。

    三、條件編譯

    一般情況下,來源程式中所有的行都被編譯。有時希望其中一部分內容只在某個條件成立或不成立時才去編譯,也就是對一部分內容指定編譯的條件,這就是條件編譯。

    條件編譯使用範式:

   1、範式一

#ifndef 標識符

程式段1

#endif

其含義是:如果沒有定義標識符,就編譯器段1。這裡的程式段1既可以是語句組,也可以是命令列。使用樣本:

#ifndef _getkey_h

#define _getkey_h

#include<sys/types.h>

#endif

這段代碼的含義是:如果沒有定義符號常量_getkey_h,就定義該常量並且包含標頭檔sys/types.h。

2、範式2

#ifndef 標識符

程式段1

#else

程式段2

#endif

其含義是:如果沒有定義標識符,就編譯器段1,否則編譯器段2。

3、範式3

#ifdef 標識符

程式段1

#endif

其含義是:如果定義了標識符,就編譯器段1,否則不編譯該程式段。

使用樣本:

#ifdef DEBUG

printf("a=%d,b=%d",a,b);

#endif

在偵錯工具時,可以在來源程式頭部加入如下語句:

#define DEBUG

這樣在軟體開發階段,編譯運行程式時會輸出變數a,b的值。當程式調試完畢,在來源程式檔案頭部刪除這一行,則使用者運行時不會輸出a,b的值。這裡列印出a,b值只是供調試使用。

4、範式四

#ifdef 標識符

程式段1

#else

程式段2

#endif

其含義是:如果定義了標識符,就編譯器段1,否則編譯器段2。

    5、範式五

#if 運算式

程式段1

#endif

其含義是:如果運算式成立,就編譯器段1,否則不編譯該程式段。

使用樣本:

#include <stdio.h>

#define MAX(x,y) (x>y?x:y)

...

int a = 5,b = 10,c;

...

#if c

c = MAX(a,b);

#endif

如果變數c存在,就調用宏MAX(a,b)獲得a,b的最大值,並把該值賦給變數c。

    6、範式六

#if 運算式

程式段1

#else

程式段2

#endif

其含義是:如果運算式成立,就編譯器段1,否則編譯器段2。

    事實上,不用條件編譯而直接用if...else語句也可以達到要求。但採用條件編譯,可以減少被編譯的語句,從而減少可執行程式的長度,縮短程式已耗用時間。當條件編譯的程式段比較多時,可執行程式的長度可以大大減少。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.