——Java教育訓練、Android教育訓練、iOS教育訓練、.Net教育訓練、期待與您交流!——
預處理指令
1、C語言在對源程式進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include檔案包含指令),産生一個新的源程式(這個過程稱為編譯預處理),之後再進行通常的編譯
2、為了區分預處理指令和一般的C語句,所有預處理指令都以符号”#”開頭,并且結尾不用分号
3、宏名一般用大寫或者以k開頭,變量名一般用小寫
4、C語言提供的預處理指令主要有:宏定義、檔案包含、條件編譯
宏定義
一般分為不帶參數的宏定義和帶參數的宏定義
不帶參數的宏定義
1、一般形式
#define 宏名 字元串
例:#define ABC 10
右邊的字元串也可以省略,比如#define ABC
2、作用
它的作用是在編譯預處理時,将源程式中所有”宏名”替換成右邊的”字元串”,常用來定義常量。
例:
#include <stdio.h>
#define Count 4
int main()
{
int ages[Count] = {, , , };
for ( int i = ; i<Count; i++)
{
printf("%d\n", ages[i]);
}
return ;
}
輸出結果:
1
2
67
89
3、作用域
預處理指令可以出現在程式的任何位置
預處理指令的作用域:從編寫指令的那一行開始,一直到檔案結尾,可以用#undef取消宏定義的作用
例:
#include <stdio.h>
#define Count 4
int main()
{
int ages[Count] = {, , , };
for ( int i = ; i<Count; i++)
{
printf("%d\n", ages[i]);
}
#undef Count; // 從此行開始取消宏定義的作用
return ;
}
帶參數的宏定義
1、定義格式:
#define 宏名(參數清單) 字元串
#define sum(v1, v2) ((v1)+(v2))
2、使用注意—括号
例:定義平方的時候不加括号
#include <stdio.h>
#define pingfang(a) a*a // 未加括号
int main()
{
int c = pingfang(+); // c = 5+5*5+5 = 35
printf("c is %d\n", c);
return ;
}
輸出結果:
c is 35
#include <stdio.h>
#define pingfang(a) ((a)*(a)) // 加括号
int main()
{
int c = pingfang(+); // c = (5+5)*(5+5) = 100
printf("c is %d\n", c);
return ;
}
輸出結果:
c is 100
3、帶參數的宏定義與函數的差別
1> 宏定義不涉及存儲空間的配置設定、參數類型比對、參數傳遞、傳回值問題
2> 函數調用在程式運作時執行,而宏替換隻在編譯預處理階段進行,是以帶參數的宏比函數具有更高的執行效率
條件編譯
隻有當程式的其中一部分代碼在滿足一定條件時才進行編譯,否則不參與編譯(隻有參與編譯的代碼最終才能被執行)
基本用法
// 條件是對宏定義進行判斷
#if 條件
...code1... // 如果條件1成立,就把code1代碼編譯進去
#elif 條件
...code2... // 如果條件2成立,就把code2代碼編譯進去
#else
...code3... // 如果條件3成立,就把code3代碼編譯進去
#endif // #endif不能少
例:
#include <stdio.h>
#define A 5
int main()
{
#if (A == 10)
printf("a是10\n");
#elif (A == 5)
printf("a是5\n");
#else
printf("a其他值\n");
#endif
return ;
}
運作結果:
a是5
if defined()和#if !defined()
判斷是否定義過某個宏
例:
// 如果定義了宏A,編譯code1
#if defined(A)
...code1...
#endif
// 如果沒有定義宏A,編譯code2
#if !defined(A)
...code2...
#endif
ifdef()和#ifndef()
#ifdef的使用和#if defined()的用法基本一緻
// 如果定義了宏A,編譯code1
#ifdef A
...code1...
#endif
#ifndef又和#if !defined()的用法基本一緻
// 如果沒有定義宏A,編譯code2
#ifndef A
...code2...
#endif
檔案包含
一般形式
1、第1種形式
#include <檔案名>
直接到C語言庫函數頭檔案所在的目錄中尋找檔案
2、第2種形式
#include “檔案名”
系統會先在源程式目前目錄下尋找,若找不到,再到作業系統的path路徑中查找,最後才到C語言庫函數頭檔案所在目錄中查找
< >表示系統自帶的檔案,” “表示自定義的檔案
使用注意
#include指令允許嵌套包含,比如a.h包含b.h,b.h包含c.h,但是不允許遞歸包含,比如 a.h 包含 b.h,b.h 包含 a.h
關鍵字typedef
作用:給已經存在的類型起一個新的名稱
使用場合
基本資料類型
例:
#include <stdio.h>
typedef int MyInt; // 給int起了個别名Myint
int main()
{
MyInt a = -;
printf("%d", a);
return ;
}
指針
#include <stdio.h>
// 給指針類型char *起一個新的類型名稱String
typedef char * String;
int main()
{
String str = "This is a string!";
printf("%s", str);
return ;
}
運作結果:
This is a string!
注意:“*”不能少
結構體
1、方式1
struct Student
{
int age;
};
typedef struct Student MyStu;
2、方式2
typedef struct Student
{
int age;
} MyStu;
枚舉
1、方式1
enum Sex {Man, Woman};
typedef enum Sex MySex;
2、方式2
typedef enum {
Man,
Woman
} MySex;
指向函數的指針
#include <stdio.h>
typedef int (*MyPoint)(int, int);
int minus(int a, int b)
{
return a - b;
}
int sum(int a, int b)
{
return a + b;
}
int main()
{
// 定義一個指向函數sum的指針p
MyPoint p = sum;
// 定義一個指向函數minus的指針p2
MyPoint p2 = minus;
// 利用指針變量p調用sum函數
int a = (*p)(, );
int b = (*p)(, );
printf("%d,%d",a,b);
return ;
}
運作結果:
9,7
typedef與#define
例:
typedef char *String1;
String1 str1, str2;
/*
經過typedef處理後,String1也算是一種資料類型,是以第行代碼相當于:
String1 str1;
String1 str2;
由于String1就是char *,是以上面的兩行代碼等于:
char *str1;
char *str2;
*/
#define String2 char *
String2 str3, str4;
/*
因為宏定義純粹是字元串替換,用char *代替String2,是以相當于:
char * str3, str4;
其實也就相當于:
char * str3;
char str4;
*/
可以看出,隻有str4是基本資料類型,str1、str2、str3都是指針類型。
是以,以後給類型起别名,最好使用typedef,而不是使用#define