1.翻譯程式第一步
在預處理之前,編譯器要進行幾部翻譯處理,主要完成以下三方面工作:
第一:把源**中出現的字元對映到源字符集,處理多位元組字元和是c外觀更加國際化的三元字元擴充套件。
第二:查詢反斜線後緊跟換行符的例項並刪除這些例項,即將類似下面的兩個物理行轉行成
printf(「 it is a beatu\
ful girl");
轉換成乙個邏輯行:
printf("it is a beatuful girl");
以為預處理表示式的長度是乙個邏輯行。
第三:將文字劃分成預處理的語言符號串行和空白字元及注釋序列。並用乙個空格代替注釋。
2.#define
指令可以出現在檔案的任何部分,其作用域從定義出現的位置到檔案的結尾。
#define two 2
#define ow "oscar wilde"
#define four two*two
#define px printf("x is %d.\n",x)
每個#define行由三部分組成。第一部分指令#define本身。第二部分縮略語,即我們稱為的巨集(本例中的稱為類物件巨集)。巨集的名字中不允許有空格,而且遵循c變數的命名規則。第三部分稱為替換列表。
從巨集變為最終的替換文字的過程稱為巨集展開。
大多數的數字常量應該使用符號常量。這樣會使程式更加的清楚,可移植。
3.語言符號
從技術角度看,系統把巨集的主體當做語言符號(token)型別字串,而不是字元型字串。c預處理器中語言符號是巨集定義主體中的單獨的「詞」。用空白字元把這些詞分開
#define four 2*2
#define six 2 * 3
第乙個定義中有乙個語言符號2*2,而第二個定義中有三個語言符號2、*、3。。在處理主體中的多個空格時,字元型字串和語言型字串採用不同的方法。字元型字串把空格也當做主體的一部分,而語言型字串只把空格當做分隔語言符號的符號
4.類函式巨集
通過使用引數可以建立和函式外形和作用類似的類函式巨集。其引數也用圓括號括起來。
#define square(x) x*x
在程式中可以這樣使用
z = square(2)
由於預處理器不進行計算,而只進行文字替換,如果使用不當會產生許多意想不到錯誤。
z = square(x+2)
z = 100/square(2)
第乙個展開後變為z = x + 2 * x + 2;第二個展開後變為z = 100 / 2 * 2;
所以在定義類函式巨集事要用圓括號括住每個引數,並括注巨集的整體定義。比如:
#define max (x, y) ((x) > (y) ? (x) : (y))
利用巨集引數建立字串: #運算子
如果想在字串中包含巨集引數。在類函式巨集的替換部分中,#符號用作乙個預處理運算子,它就可以吧語言符號轉化為字串。x是乙個巨集參量,#x就可以把引數轉換為相應的字串。
預處理器的粘合劑:##運算子
#define xname(n) x ## n
這樣呼叫 xname(4),展開後:x4。進行語言符號的粘合操作。
5.#include 標頭檔案
標頭檔案中最常見的內容:
明顯常量 :stdio.h中的eof、null和bufsize等
巨集函式 :getchar()
函式宣告:
型別定義:
另外,將多個源檔案共享的外部變數放到標頭檔案中。
包含標頭檔案的另一種情況:使用具有檔案作用域、內部鏈結和const限定詞的變數和陣列。使用const可以避免值被意外的修改。使用static後,每個包含該標頭檔案的檔案都獲得乙份該常量的副本。因此不需要在乙個檔案中進行定義宣告,在另乙個檔案中進行引用宣告。
6.條件編譯
使用這些指令告訴編譯器:根據編譯時的條件節後或忽略資訊塊。
(1)#ifdef、#else和#endif
#ifdef vis
#include 「horse.h」
#define ata 5
#else
#include 「cow.h」
#define btb 5
#endif
(2)#ifndef指令
#ifndef可以和#else、#endif一起使用。#ifndef判斷後面的識別符號是否未定義。#ifndef通常用來定義此前未定義的常量。
#ifndef size
#define size 100
#endif
該指令通常還用來防止多次包含同一檔案。
/*things.h*/
#ifndef things_h_
#define things_h_
/*標頭檔案的其餘部分*/
#endif
(3)#if和#elif指令
#if指令更像c中的if;#if常跟常量表示式。如果表示式為非零值,則表示式為真。
#if sys == 1
#include "i.h"
#elif
#include "j.h"
#elif
#include "g.h"
#endif
(4)#line 和#error
#line指令用於重置__line__和__file__巨集報告的行號和檔名。
(5)#pragm將編譯器指令置於源**中。
C預處理器和C庫
編譯程式之前,先由預處理器檢查程式。根據程式中使用的預處理器指令,預處理器用符號縮略語所代表的內容替換程式中的縮略語。1.編譯器的處理步驟 2 編譯器查詢反斜線後面緊跟換行符的例項並刪除這些例項。將多個物理行替換為乙個邏輯行。3 編譯器將文字劃分為預處理的語言符號 token 序列和空白字元及注釋序...
C 標準庫 預處理器
1.預處理器 1.1 使用 代表返回乙個帶引號的字串,如 define to string s s to string hello 可以表示成 hello 1.2 使用 代表連線前後的內容,如 define concatenate x,y x y concatenate 5,2 可以表示成52 1....
C 預處理器
偶爾翻c 的教材,看到了一些以前自己不太關注的角落。參考教材 c 大學教程 harvey m.deitel 和paul james deitel著。預處理發生在編譯之前,包括把其他檔案包含到要編譯的檔案中 定義符號常量和巨集 程式 的條件編譯以及預處理指令的條件執行。對應的,預處理指令有 檔案包含命...