linuxC學習第二十一天
一、預編譯相關
1、define
(1)define的用法
(1)#define定義巨集常量可以出現在程式碼的任何地方
(2)從#define巨集定義位置開始,以後的程式碼就都可以使用這個巨集了
(3)編譯器會在預處理的時候用真身替換巨集
(2)定義函式
#define SUM(a, b) ((a)+(b))
(3)撤銷定義
#Undef SUM
(4)內建巨集
LINE:表示正在編譯的檔案的行號
FILE:表示正在編譯的檔案的名字
DATE:表示編譯時刻的日期字串
TIME:表示編譯時刻的時間字串
FUNCTION:表示編譯時候所在的函式
2、ifdef
1、ifdef條件編譯有3種方式
(1)#ifdef…#else…#endif
#ifdef 識別符號
程式段1
#else
程式段2
#endif
它的功能是:如果識別符號已被#define命令定義過,則對程式段1進行編譯;否則對程式段2進行編譯。如果沒有程式段2(它為空),本格式種的#else可以沒有,既可以寫為:
#ifdef 識別符號
程式段
#endif
(2)#ifdef…#else…#endif
#ifndef 識別符號
程式段1
#else
程式段2
#endif
與上一種形式的區別是ifdef改為ifndef。它的功能是:如果識別符號未被#define命令定義過,則對程式段1進行編譯;否則對程式段2進行編譯。這與第1種形式的功能正好相反
(3)#if…#else…#endif
#if 常量表達式
程式段1
#else
程式段2
#endif
它的功能是:如果常量表達式的值為真(非0),則對程式段1進行編譯;否則對程式段2進行編譯。因此可以使程式在不同條件下編譯,完成不同的功能。
3、#和##
1、功能
#用於在與編譯期間將巨集引數轉化為字串
##用於在預編譯期間粘連兩個符號
二、一些關鍵字
1、typedef(關鍵字)
1、功能:
使用關鍵字 typedef 可以為型別起一個新的別名
2、給普通型別起名字
typedef int INTEGER;
注意要加 ;
3、給數值型別起名字
typedef char ARRAY20[20];
4、給結構體型別起名字2種形式
(1)
typedef struct stu
{
char name[20];
int age;
char sex;
} STU;
(2)
struct stu
{
char name[20];
int age;
char sex;
} ;
typedef struct stu STU
5、給函式指標型別起名字
typedef int(*PFunc)(int a,int b)
6、與define的區別
typedef 在表現上有時候類似於 #define,但它和巨集替換之間存在一個關鍵性的區別。正確思考這個問題的方法就是把 typedef 看成一種徹底的“封裝”型別,宣告之後不能再往裡面增加別的東西。
(1) 可以使用其他型別說明符對巨集型別名進行擴充套件,但對 typedef 所定義的型別名卻不能這樣做。如下所示:
#define INTERGE int
unsigned INTERGE n; //沒問題
typedef int INTERGE;
unsigned INTERGE n; //錯誤,不能在 INTERGE 前面新增 unsigned
(2) 在連續定義幾個變數的時候,typedef 能夠保證定義的所有變數均為同一型別,而 #define 則無法保證。例如:
#define PTR_INT int *
PTR_INT p1, p2;
經過巨集替換以後,第二行變為:
int *p1, p2;
這使得 p1、p2 成為不同的型別:p1 是指向 int 型別的指標,p2 是 int 型別。
相反,在下面的程式碼中:
typedef int * PTR_INT
PTR_INT p1, p2;
p1、p2 型別相同,它們都是指向 int 型別的指標。
2、return(關鍵字)
用來終止一個函式並返回其後面跟著的值
3、static(關鍵字)
1、用於修飾變數(靜態變數)
變數又分兩種型別
(1)區域性變數:修飾區域性變數的時候,可以增加區域性變數的壽命。加上staric就是靜態變量了,存放在資料區,不在是棧。當出棧後這個變數的值還是存在著,直到程式結束才釋放掉
(2)全域性變數:修飾全域性變數的時候,可以令這個全域性變數只能在本檔案中使用,其他檔案就算加上extern也無法使用(就是隱藏了起來)。
2、用於修飾函式(靜態函式)
令函式只能在本檔案中使用,好處在不同的人編寫函式時,不用怕名字重複。
4、const(關鍵字)
1、用於修飾變數
將變數改成只讀屬性,不能通過修飾變數名來改變變數空間的值
注意:const不能通過變數名改變變數空間的值但可以通過其他方式改變,例如指標(一般不推薦)
2、修飾陣列
定義或說明一個只讀陣列可採用如下格式:
int const a[5] = {1,2,3,4,5}; 或 const int a[5] = {1,2,3,4,5}
3、修飾指標
const int * p; // p可變,p指向的物件不可變
int const * p; // p可變,p指向的物件不可變
int * const p; // p不可變,p指向的物件可變
const int * const p; // 指標p和p指向的物件都不可變
這裡給出一個記憶和理解的方法:
先忽略型別名(編譯器解析的時候也是忽略型別名),我們看const離哪個近,“近水樓臺先得月”,離誰近就修飾誰。
const (int) p //const 修飾p,p是指標,p是指標指向的物件,不可變。
(int) const * p; //const 修飾p,p是指標,p是指標指向的物件,不可變。
( int) * const p;//const 修飾p,p不可變,p指向的物件可變,即p可變
const ( int)* const p; // 前一個const修飾*p,後一個const修飾p,指標p和p指向的物件都不可變
4、修飾陣列
const修飾也可以修飾函式的引數,當不希望這個引數值在函式體內被意外改變時使用。格式如下:
void Fun(const int *p)
5、修飾返回值
const也可以用於修飾函式的返回值,返回的數值不能改變,格式如下:
const int Fun(int *p)
5、extern(關鍵字)
1、 變數宣告
變數宣告就是給變數一個名字,讓下面的程式知道有這個變數去其他檔案中找。
注意的是變數宣告只有名字,沒有空間。
2、extren:用於變數的宣告,當你使用多個檔案時想要用其他檔案中定義的變數就要用extern進行變數的宣告