之前我們說過,源程序需要經過預處理、編譯、彙編、鏈接纔會變成可執行程序,預處理階段完成的是預處理操作,本質上是一種替換操作。
宏
不帶參宏
宏常量
宏常量是用 #define 定義的宏,只能在一行內表達,如果要在多行內表達,則需要加上連接符\。比如:
#define PI 3.14
宏常量很多情況下可以用來定義文件路徑。但要記住:宏只是簡單的替換操作
宏類型
有時候,也會用宏來定義一種合成的類型名。如:
#include CHAR_POINTER char *
但要記住:宏只是簡單的替換操作,不要和 typedef 弄混
帶參宏
宏函數
有時候,對於一些簡單的函數也可以利用宏來實現。如:
#define MAX(a,b) a>b?a:b
宏名和參數之間不能出現空格。雖然這樣可以簡化代碼,減少程序調用,但是編譯文件會很大。
仍然要記住:宏只是簡單的替換操作
取消宏
取消宏常量,宏類型,宏函數
對於已經定義的宏常量,宏類型和宏函數來說,取消宏定義都只有一句話:
#undef macroname
預定義宏
在 C 語言中,還存在着一些內置的已經定義的宏,如:
__DATE__ | 進行預處理的日期 |
__FILE__ | 代表當前源代碼文件名的字符串文字 |
__LINE__ | 代表當前源代碼中的行號的整數常量 |
__TIME__ | 源文件編譯時間 |
__func__ | 當前所在函數名 |
條件編譯
在跨平臺開發的時候,有時候會根據條件選擇性的進行編譯,這就是條件編譯。
單雙路
一般結構爲:
#ifdef
......
#else
......
#endif
或者是:
#ifndef
......
#else
......
#endif
單雙多路
一般結構爲:
#if logical statement
......
#elif logical statement
......
#elif logical statement
......
#endif
#include
在 main 之前除了條件編譯之外,一般都會有 #include 語句,這就是頭文件包含。
包含方式
包含是指被包含的文件全部包含到當前的文件中。包含方式一般有兩種:
<>
使用這種方式是指從指定路徑中搜索幷包含頭文件。
""
使用這種方式是指從當前工程路徑中搜索幷包含頭文件,當前工程路徑下不存在的話,纔到系統路徑下搜索幷包含。
多文件編程
多文件編程會增加程序的可讀性,除了方便管理之外還能夠增加文件的可移植性和保密性。
這裏以一個簡單的圖示簡單說明一下:
- C 語言是以文件爲單位進行編譯的,編譯期間只需要進行函數聲明即可
- 鏈接階段提供實現就能夠生成可執行文件
- else.h 中的條件編譯語句是爲了避免頭文件重複包含
關於 #
利用 # 創建字符串
如果要創建類似 "str1",“str2”,"str3" 這樣的字符可能就需要 # 運算符。看下邊的程序:
#include <stdio.h>
#define str(x) "str"#x
int main()
{
printf("%s\t%s\t%s",str(1),str(2),str(3));
return 0;
}
結果爲:
str1 str2 str3
以上的結果是由於類似於 “abc”"def""ghi" 這樣的字符串是合理的。而 # 號作爲一個預處理運算符,它能夠將待替換符轉化爲字符串。
利用 ## 進行預處理參數粘合
看下邊的程序:
#include <stdio.h>
#define SUM(a,b) (a##a+b##b)
#define XVAR(n) x##n
int main()
{
int XVAR(1) = 1,XVAR(2) = 2;
printf("SUM(1,2) = %d\n",SUM(1,2));
printf("XVAR(1) = %d,XVAR(2) = %d\n",x1,x2);
printf("&XVAR(1) = %p,&XVAR(2) = %p\n",&XVAR(1),&XVAR(2));
printf("&x1 = %p,&x2 = %p",&x1,&x2);
return 0;
}
結果爲:
SUM(1,2) = 33
XVAR(1) = 1,XVAR(2) = 2
&XVAR(1) = 0060FEAC,&XVAR(2) = 0060FEA8
&x1 = 0060FEAC,&x2 = 0060FEA8
還可以將上邊的程序改爲:
#include <stdio.h>
#define XVAR(n) x##n
#define PRINT_VAR(n) printf("XVAR("#n") = %d",x##n);
#define POINTER_VAR(n) printf("&XVAR("#n") = %p",&XVAR(n));
#define POINTER_X(n) printf("&x"#n" = %p",&x##1);
int main()
{
int XVAR(1) = 1,XVAR(2) = 2;
PRINT_VAR(1);
putchar(10);
PRINT_VAR(2);
putchar(10);
POINTER_VAR(1);
putchar(10);
POINTER_VAR(2);
putchar(10);
POINTER_X(1);
putchar(10);
POINTER_X(2);
return 0;
}