程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 編譯預處理和動態存儲分配(1),編譯預處理

編譯預處理和動態存儲分配(1),編譯預處理

編輯:關於C語言

編譯預處理和動態存儲分配(1),編譯預處理


1 編譯預處理

  C語言中,凡是以“#”號開頭的行,都稱為“編譯預處理”命令行。C語言的預處理命令有:#define, #undef, #include, #if, #else, #elif, #endif, #ifdef, #ifndef, #line, #pragma, #error。

  1.1 宏替換

  1.1.1 不帶參數的宏定義

  (1)不帶參數的宏定義命令行形式如下:

    #define  宏名  替換文本

  在#define、宏名和宏替換文本之間用空格隔開。例如:

    #define  SIZE  100

  (2)替換文本中可以包含已定義過的宏名,例如:

    #define  PI        3.14

    #define  ADDPI      (PI + 1)

    #define  TWO_ADDPI   (2 * ADDPI)

  (3)當宏定義在一行中寫不下,需要在下一行繼續時,只需在最後一個字符後緊接著加一個反斜線“\”。例如:

    #define  LEAP_YEAR  year % 4 == 0\

    && year % 100 != 0 || year % 400 == 0

  如果在“\”前或在下一行的開頭留有空格,則在宏替換時也將加入這些空格。

  (4)同一宏名不能重復定義,除非兩個宏定義命令行完全一致。

  (5)替換文本不能替換雙引號中與宏名相同的字符串。例如,如果YES是已定義的宏名,則不能用與它相關的替換文本來替換 printf("YES") 中的YES。

  (6)替換文本不會替換用戶標識符中的成分。例如,宏名 YES,不會替換標識符 YESORNO 中的 YES。

  (7)用作宏定義的標識符通常用大寫字母表示,這並不是語法規定,只是一種習慣,便於與程序中的其他標識符相區別。

  (8)C程序中,宏定義的定義位置一般寫在程序的開頭。

  1.1.2 帶參數的宏定義

  (1)帶參數的宏定義命令行形式如下:

    #define  宏名( 形參表 )  替換文本

  例如:

    #define  MU(X, Y)  ((X) * (Y))

  以上宏定義命令行中,MU(X, Y) 簡稱為“宏”,MU是用戶標識符,稱為宏名。宏名和左括號 "(" 必須緊挨著,它們之間不得留有空格。其中一對圓括號中由若干稱為形參的標識符組成,各形參之間用逗號隔開。“替換文本”中應包含有形參。

  (2)和不帶參數的宏定義相同,同一宏名不能重復定義,除非兩個宏定義命令行完全一致。

  (3)在調用帶參數的宏名時,一對圓括號必不可少,圓括號中實參的個數應該與形參個數相同,若有多個參數,它們之間用逗號隔開。在預編譯時,編譯預處理程序用“替換文本”來替換宏,並用對應的實參來替換“替換文本”中的形參。

  (4)在“替換文本”中的形參和整個表達式應該用括號括起來,例如:

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

  (5)宏替換和函數調用有相似之處,但在宏替換中,對參數沒有類型要求。例如,調用 MU,既可以求兩個整型數的乘積,也可求兩個實型數的乘積。而如果是調用函數來求兩個數的乘積,則對不同類型的參數就需要定義不同的函數。

  (6)宏替換是在編譯前由預處理程序完成的,因此宏替換不占用運行時間。而函數調用是在程序運行時進行的,在函數調用過程中需要占用處理時間。

  1.1.3 終止宏定義

  可以用 #undef 提前終止宏定義的作用域。例如:

    #define PI 3.14

    main()

    ...

    #undef PI

    ...

  以上 PI 的作用域從#define PI 3.14 命令行開始,到#undef PI 命令行結束。從#undef 之後 PI 變成無定義,不再代表3.14。

  1.2 文件包含

  C語言開發程序時,可以把一些宏定義按照功能分別存入不同的文件中。當需要使用某類宏定義時,就無需在程序中重新定義,而只要把這些宏定義所在的文件包含在程序的開頭就可以了。

  所謂文件包含,是指在一個文件中去包含另一個文件的全部內容。C語言用#include 命令行來實現文件包含的功能。#include 命令行的形式如下:

    #include  "文件名"

  或

    #include  <文件名>

  預編譯時,預編譯程序將用指定文件中的內容來替換此命令行。a.如果文件名用雙引號括起來,系統先在源程序所在的目錄內查找指定的包含文件,如果找不到,再按照系統指定的標准方式到相關目錄中查找;b.如果文件用尖括號括起來,系統將直接按照系統指定的標准方式到有關目錄查找。

  說明:

  (1)包含文件的#include 命令行通常應書寫在所用源程序文件的開頭,故包含文件又稱作“頭文件”。頭文件名可以由用戶指定,其後綴不一定用“.h”。

  (2)包含文件中,一般包含有一些公用的#define命令行、外部說明或對庫函數的原型說明。例如 stdio.h 就是這樣的頭文件。

  (3)當包含文件修改後,對包含文件的源程序必須重新進行編譯連接

  (4)一個程序中,允許有任意多個#include命令行。

  例題1:使用帶參數的宏定義,定義宏MYALPHA(c),用來判斷字符是否為字母

1 #include <stdio.h> 2 //宏定義判斷輸入字符是否為字母 3 #define MYALPHA(c) ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)\ 4 ? 1 : 0) 5 int main() 6 { 7 char ch; 8 9 printf("Please enter a character 'c'.\n"); 10 printf("Enter 'f' or 'F' to finish.\n"); 11 12 /* 13 scanf函數會把輸入中的換行符讀進來,為防止換行符的讀入使用修飾符‘*’ 14 ‘*’號符:表示不將輸入項賦予相應的變量。如: 15 scanf("%c %*c %c", &cha, &chb); 16 當輸入:m n q時,則把m賦給變量cha,n跳過,q賦給變量chb 17 */ 18 scanf("%c%*c", &ch); 19 20 while (ch != 'f' && ch != 'F') 21 { 22 printf("The ASCII code of character is: %d\n", ch); 23 24 if (MYALPHA(ch)) 25 { 26 printf("c is a character.\n"); 27 } 28 else 29 { 30 printf("c is not a character.\n"); 31 } 32 33 scanf("%c%*c", &ch); 34 } 35 return 0; 36 } 37 #undef MYALPHA //終止宏定義作用域 MYALPHA

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved