C Primer Plus--C預處理器和C庫(2)

#include指令

  • #include <頭文件.h>//在標準系統目錄中尋找頭文件
  • #include “頭文件.h”//先在當前目錄下面尋找頭文件,然後在標準系統目錄下尋找頭文件

預處理器在碰到#inclide指令時,就會將後面附加的頭文件的內容包含到當前文件中。

頭文件

後綴爲.h的文件是頭文件。這類文件經常包含預處理器所需要的語句。
頭文件內容最常見形式包括:

  • 明顯常量
  • 宏函數
  • 函數聲明
  • 結構模板定義
  • 類型定義

其他指令

#undef

#undef指令取消一個給定的已定義#define.

#define FF 10

#undef FF //FF定義被取消

條件編譯

#ifdef #else #endif

#ifdef後面的標識符如果已經定義了,那麼執行它的分支控制的指令,知道下一個#else#endif爲止。如果有#else存在,那麼在未定義時會執行#else知道#endif之間的所有指令。

#define FF 10

#ifdef FF
#define AA 100
#else
#define AA 1000
#endif

int main() {
    printf("FF :%d\n",AA);
}

#ifndef

#ifndef#ifdef的反義詞,它是用來確定後面的表示符未被定義。通常用來定義此前未被定義的常量。

#ifndef FF
#define FF 199
#endif
int main() {
    printf("FF :%d\n",FF);
}

#ifndef也可以用於防止多次包含同一文件。

/*
 *假設這個頭文件是test.h
 */
 //原本頭文件的內容直接寫,現在我們把頭文件的內容放到下面這樣的結構裏:
 #ifndef _TEST_H
 #define _TEST_H
 /*
  *#define和#endif之間存放頭文件的所有內容
  */
 #endif

來看看上面這段代碼什麼意思:
首先,明確我們的目的:防止一個文件被多次的include。爲什麼會存在多次include呢?因爲可能一個文件會include多個文件,而不同文件有可能include同一個文件,而在一個文件中只能對一個文件中include一次。舉個栗子:存在a.h,b.h,test.h,有可能a.h中有一個#include "test.h",同時b.c中有兩行

#include "a.h"
#include "test.h"

這樣就出現了b.h被包含了兩次,而C是不允許這樣的。上面用到#ifndef就解決了這個問題。
test.h未被定義,也就是說這個頭文件被第一次包含了,會定義一個_TEST_H的常量,但沒有body,因爲我們不需要這個常量具有body。這時候頭文件裏的所有內容被預處理器執行。當test.h被第二次包含時,預處理器檢測到已經存在_TEST_H這個量,就會跳過,也就不會重複執行頭文件裏的內容了。**這裏的關鍵是保持_TEST_H的唯一。我們這裏用頭文件的文件名做標識符,將文件名前面加下劃線,並將點換成下劃線,能夠保證這個標識符不重複。**但這種做法是編譯器提供商爲了標準頭文件採用的方法,我們平時自己寫的時候要想防止與標準頭文件衝突,就不要按這種方法來取標識符。例如可以把下劃線加到文件名後面等等。

#if#elif

#if#elif後面跟常量整數表達式,當這個表達式值爲非0值時爲真,爲0位假,類似於C程序中的if-else分支結構。可以應用C的關係運算符以及邏輯運算符。

#if defined(FF)
#define SS 9999
#elif defined(_TEST_H)
#define EE 99
#endif

預定義宏

一些常見的預定義宏:

意義
__DATE__ 進行預處理操作的日期字符串
__FILE__ 當前源代碼文件名的字符串
__LINE__ 當前所在代買行號
__TIME__ 源文件編譯時間
__STDC_VERSION__ 當前編譯器遵循的C標準版本,當爲C99時值爲199901L

#line#error

#line指令用於重置由__LINE____FILE__宏報告的行號和文件名。
使用方法:

#line 100 //當前行號重置爲100
#line 10 "test.c" //把行號重置爲10,文件名重置爲test.c
printf("%d\n",__LINE__);
#line 1000
printf("%d\n",__LINE__);
printf("%d\n",__LINE__);

#error指令使預處理器發出一條錯誤消息,該消息包含指令中的文本。可能的話,編譯過程應該中斷。

#if __STDC_VERSION__ != 199901L
#error Not C99
#endif

內聯函數

內聯函數主要是爲了把解決函數調用過程中建立調用、傳遞參數、跳轉到函數代碼段返回耗費的時間較長的問題。它適用於較短代碼塊,創建內聯函數需要用到inline關鍵字。

inline double square(double x);
double square(double x){
    return x*x;
}
int main() {
    double a = square(3);
    printf("%lf\n",a);
}
//內聯函數這裏其實把函數體直接寫到了main裏面,不用調用了。
/*
 *int main(){
 *	double a = a * a;
 *	printf("%lf\n",a);
 *}
 */

無法獲取內聯函數的地址,因爲內聯函數並沒有被分配單獨的空間。內聯函數適用於短小函數,長的函數調用造成的時間遠遠小於函數體執行時間,使用內聯函數並沒什麼意義。
內聯函數的定義和對該函數的調用必須在同一文件中。因此,內聯函數一般具有內部鏈接。在多文件程序中,要想使用相同的內聯函數,必須在每個文件中對內聯函數進行定義。爲了方便,可以把內聯函數的定義放在頭文件中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章