C语言程序设计 | 程序环境和预处理:翻译环境和执行环境、宏、条件编译
程序環境和預處理:
- 翻譯環境和執行環境
- 宏
- 條件編譯
翻譯環境和執行環境
在ANSI C的任何一種實現中,存在兩種不同的環境。
第一種是翻譯環境,在這個環境中源代碼被轉換成可執行的機器指令。第二種是執行環境,它用于實際執行代碼。
翻譯環境
我們寫的代碼是如何從一開始的.c文件變化為可執行的.exe文件,就是在這一步完成的。
- 組成一個程序的每個源文件通過編譯過程分別轉換成目標代碼
- 每個目標文件由鏈接器捆綁在一起,形成一個單一而完整的可執行程序
- 鏈接器同時也會引入標準C函數庫中任何被該程序所用到的函數,而且還可以搜索本地的程序庫,找到需要的函數鏈接進程序中
下面就來詳細講一下編譯的具體過程
編譯分為三個階段,預處理,編譯,匯編。
1.預處理
步驟:
- 展開頭文件
- 宏替換
- 去掉注釋
- 條件編譯
經過上述步驟后將.c文件處理成為.i文件
2.編譯
步驟:
- 語法檢查
- 將代碼轉換為匯編代碼
這時.i文件會被處理成.s文件
3.匯編
步驟:
- 將匯編代碼轉換成為機器所能識別的二進制
這一步后,s文件被處理成為.o文件。
編譯器的工作完成以后,就到了鏈接器的工作
鏈接
步驟:
- 將聲明卻又未定義的函數在其他文件中找到
這時候,多個.o文件將被處理成為可執行的exe文件。
運行環境
程序執行的過程:
宏
#define 定義宏
#define允許我們將一個文本替換另一個文本,也允許我們將參數替換到文本當中,這種實現通常稱之為宏
#define 替換 被替換例如:
#define type int #define num 100 int main() {int a = 100;type b = num;printf("%d %d\n", a, b); }
它們運行后是一樣的,宏的作用就是將一個參數或者標識符在預處理階段就可以替換成我們想要的名字。
宏也可以當作函數使用
聲明方法:
注意:參數列表的左括號必須與name緊鄰。如果兩者之間存在空格,參數列表就會被解釋為stuff的一部分
如果是對宏不太了解的人,可能會遇到下面這種情況
#define SQUARE( x ) x * x int main() {int a = 5;printf("%d\n", SQUARE(5));printf("%d\n", SQUARE(5 + 1)); }
第一個答案是我們意料中的,但是第二個答案卻讓人感到奇怪,明明我們的參數是5 + 1,得到的應該是6的平方36,為什么會是這個奇怪的值呢?
之前我提到過,宏是單純的替換,而非計算后再替換,所以替換后的公式如下
所以如果我們要使用宏函數,就必須要考慮到優先級問題,所以要在定義宏時加上括號
對于這個新的宏,我們按照之前的做法加上了括號,但是得到的答案還是錯的,我們再次將宏替換進代碼中
這個問題還是優先級的問題,所以我們需要再在外面加上一層括號
總結:所以用于對數值表達式進行求值的宏定義都應該用這種方法加上括號,避免在使用宏時由于參數中的操作符或臨近操作符之間不可預料的相互作用
#define的替換規則
在程序中拓展#define定義符號和宏時,需要涉及幾個步驟
注意:
- 宏參數和#define定義中可以出現其他#define定義的變量。但是對于宏,不能出現遞歸。
- 當預處理器搜索#define定義的符號的時候,字符串常量的內容并不被搜索
宏與函數的對比
優點:
缺點:
條件編譯
條件編譯,顧名思義,就是滿足條件才編譯某些語句,不滿足則不編譯。
在我們編寫代碼的時候,可能存在一種情況,這段語句在某個環境下是需要的,在另一個環境下卻又不需要,這個時候我們如果要在它不用的時候將它刪除,就會十分麻煩,而使用條件編譯就可以解決這個方法。
例如當我們一個項目中多次引用一個頭文件,造成在最終程序中出現了多份這個頭文件的內容,導致了文件內容重復的情況,這個時候我們就需要這個條件編譯
#ifndef __TEST_H__ #define __TEST_H__ #endif這就是一種條件編譯
常見的條件編譯如下:
1.
多個分支的條件編譯
#if (常量表達式) #elif (常量表達式) #else #endif判斷是否被定義
#if defined(x) #ifdef x#if !defined(x) #ifndef x嵌套指令
#if defined(OS_UNIX)#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif#elif defined(OS_MSDOS)#ifdef OPTION2msdos_version_option2();#endif#endif總結
以上是生活随笔為你收集整理的C语言程序设计 | 程序环境和预处理:翻译环境和执行环境、宏、条件编译的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言程序设计 | 动态内存管理:动态内
- 下一篇: 数据结构与算法 | 顺序表