編譯預處理
在對一個源程序進行編譯時,系統將自動調用預處理程序對源程序中的預處理部分作處理,處理完畢后自動編譯源程序
宏定義
不帶參數的宏定義
? ? ? ? #define? 標識符? 字符串
? ? ? ? #define PI 3.1415926
? ? ? ?“標識符”是為所定義的宏名
? ? ? ?“字符串”為宏名將要被替換的字符串,可以是常量字符串、表達式字符串、格式字符串等?
宏定義
常量宏定義
//【例9. 1】常量的宏定義。
#include <stdio.h>
#define PI 3.1415926
void main()
{ float r,l,s,v;printf("Input radius: ");scanf("%f",&r);l=2.0*PI*r; //宏展開為 l=2.0*3.1415926*r;s=PI*r*r; //宏展開為 s=3.1415926*r*r;v=4.0/3*PI*r*r*r; //宏展開為 v=4.0/3*3.1415926*r*r*r;printf("l=%.4f\ns=%.4f\nv=%.4f\n",l,s,v);
}
表達式的宏定義
//【例9. 2】表達式的宏定義。
#include <stdio.h>
#define M (y*y+3*y)
void main()
{ int s,y;printf("Input a number: ");scanf("%d",&y);s=3*M+4*M+5*M; //宏展開為 s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y);printf("s=%d\n",s);
}
函數名和格式字符串的宏定義
//【例9. 3】函數名和格式字符串的宏定義。
#include <stdio.h>
#define P printf
#define F "%4d\t%.2f\n"
void main()
{ int a=3, c=5, e=11;float b=4.6, d=7.9, f=22.08;P(F,a,b); //宏展開為 printf("%4d\t%.2f\n",a,b);P(F,c,d); //宏展開為 printf("%4d\t%.2f\n",c,d);P(F,e,f); //宏展開為 printf("%4d\t%.2f\n",e,f);
}
宏
????????define PI 3.l4l5926
????????把數字“1”寫成了小寫字母“l”
????????#define PI 3.1415926;
????????……
????????area=PI*r*r;
????????……
????????宏展開后為: area=3.1415926;*r*r;
//【例9. 4】雙引號中與宏名相同的字符不作替換。
#include <stdio.h>
#define PI 3.1415926
void main()
{ printf("PI\n"); //不進行宏展開printf("%f\n",PI); //進行宏展開
}
????????(8)宏定義必須寫在函數之外,其作用域為宏定義命令起到源程序結束。如要終止其作用域可使用# undef命令。
//【例9. 5】使用# undef結束宏的作用域。
#include <stdio.h>
#define PI 3.1415926
void main()
{ float r=2,area;area=PI*r*r;
//宏展開為area=3.1415926*r*r; printf("area=%f",area);
}
#undef PI
f1()
{ float r=2,area;area=PI*r*r;
//PI不能被宏展開,此處語法報錯,PI沒有定義printf("area=%f",area);
}
帶參數的宏定義
//【例9. 6】帶參數的宏定義。
#include <stdio.h>
#define MAX(a,b) (a>b)?a:b
void main()
{ int x,y,max;printf("Input two numbers:");scanf("%d,%d",&x,&y);max=MAX(x,y); //宏展開為 max=(x>y)?x:y;printf("max=%d\n",max);
}
語句:?????????? max=MAX(x,y);
宏展開后為:max=(a,b)? (a>b)?a:b(x,y); 是錯誤的。
(2)宏定義中的形參是標識符,語句中的實參可以是表達式
【例9. 7】語句中的實參為表達式。
#include <stdio.h>
#define SQ(y) (y)*(y)
void main()
{ int a,sq;printf("Input a number: ");scanf("%d",&a);sq=SQ(a+1); //宏展開為 sq=(a+1)*(a+1);printf("sq=%d\n",sq);
}
(3)在宏定義中,形參通常要用括號括起來以避免出錯。
宏定義:
?????? #define SQ(y) (y)*(y)
中(y)*(y)表達式的y都用括號括起來,因此結果是正確的
如果去掉括號,定義形式如下:
?????? #define SQ(y) y*y
語句:??????????? sq=SQ(a+1);
宏展開后為:sq=a+1*a+1;
按以下形式定義:
??????????? #define SQ(y) (y)*(y)
語句:sq=1.0/SQ(a+1);
宏展開后為:
??????????? sq=1.0/(a+1)*(a+1);??? //先算除法,再算乘法
要想先算乘法后算除法,應該在宏定義中的整個字符串外加括號,按如下形式定義:
????????? #define SQ(y) ((y)*(y))
帶參數的宏和函數的區別
//【例9. 8】通過宏展開得到若干結果。
#include <stdio.h>
#define SSSV(L,W,H,SA,SB,SC,VV) SA=L*W;SB=L*H;SC=W*H;VV=W*L*H;
void main()
{ int l=3,w=4,h=5,sa,sb,sc,vv;SSSV(l,w,h,sa,sb,sc,vv); //宏展開后為sa=l*w;sb=l*h;sc=w*h;vv=w*l*h;printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);
}
調用函數只可得到一個返回值,而宏可以設法得到幾個結果。
文件包含
文件包含命令的一般形式為:
#include "文件名"
或
#include <文件名>

//【例9. 9】文件包含命令的使用。
(1)文件file1.c內容如下:
#include <stdio.h>
#include "file2.c"
void main()
{ int a,b,c;printf("Input two numbers: ");scanf("%d,%d",&a,&b);c=max(a,b);printf("max=%d\n",c);
}
//(2)文件file2.c內容如下:
int max(int x,int y)
{ int z;if(x>y) z=x;else z=y;return(z);
}
條件編譯
條件編譯-形式一
#ifdef? 標識符
? 程序段1
#else
? 程序段2
#endif
#ifdef? 標識符
? 程序段
#endif
功能是:如果所指定標識符在之前已被 #define命令定義過,則在編譯時編譯程序段1;否則編譯程序段2。
【例9. 10】給定半徑r,求圓的面積s。要求設置條件編譯:若π值已定義,則直接計算面積;若π值未定義,則定義π值后再計算面積。
#include <stdio.h>
void main()
{??? float r,s;
??? printf("Input radius:? ");
??? scanf("%f",&r);
??? #ifdef PI??? //條件編譯
??????? s=PI*r*r;????????????? //程序段1
??? #else
??????? #define PI 3.1415926?? //程序段2
??????? s=PI*r*r;????????????????
??? #endif
??? printf("s=%f\n",s);
}
(1)程序中在條件編譯前未定義π值(即PI),所以編譯程序段2
(2)若程序開頭加入宏定義“#define PI 3.1415926”,則編譯程序段1?
條件編譯-形式二
#ifndef 標識符
? 程序段1
#else
? 程序段2
#endif
功能是:如果標識符之前未被#define命令定義過,則對程序段1進行編譯,否則對程序段2進行編譯
【例9. 11】按形式二修改【例9. 10】的程序。
#include <stdio.h>
void main()
{??? float r,s;
??? printf("Input radius:? ");
??? scanf("%f",&r);
??? #ifndef PI?? //條件編譯
??????? #define PI 3.1415926?? //程序段1
??????? s=PI*r*r;????????????????
??? #else
??????? s=PI*r*r;????????????? //程序段2
??? #endif
??? printf("s=%f\n",s);
}
(1)程序中在條件編譯前未定義π值(即PI),所以編譯程序段1
(2)若在程序的開頭加入宏定義“#define PI 3.1415926”,則編譯程序段2
條件編譯-形式三
#if 表達式
? 程序段1
#else?
? 程序段2
#endif
功能是:若表達式的值為真(非0),則編譯程序段1,否則編譯程序段2
【例9. 12】設置條件編譯。求圓的面積或正方形的面積。
#include <stdio.h>
#define PI 3.1415926
#define R 1
void main()
{??? float c,s;
??? printf ("Input a number:? ");
??? scanf("%f",&c);
??? #if R??????? //條件編譯
??????? s=PI*c*c;?????????? //程序段1
??????? printf("Area of circle is : %f\n",s);
??? #else
??????? s=c*c;???????????????? //程序段2
??????? printf("Area of square is : %f\n",s);
??? #endif
}
程序宏定義中,定義R為1,因此在條件編譯時,表達式R的值為真,故編譯程序段1,求圓的面積
說明
#ifdef COMPUTER_A
? #define INTEGER_SIZE 16
#else
? #define INTEGER_SIZE 32
#endif