首页 > 代码库 > C语言第十一回合:预处理命令的集中营
C语言第十一回合:预处理命令的集中营
C语言第十一回合:预处理命令的集中营
【学习目标】
1. 宏定义
2. 文件包括”处理
3. 条件编译
预处理命令:能够改进程序设计的环境。提高编程效率。
其功能主要有三种:宏定义、文件包括、文件编译。
ANSI标准定义的C语言预处理指令预览表
A: 宏定义
(a)不带參数的宏定义
格式:#define标识符 字符串
如:#define PI 3.1415926
*标识符被称为:宏名
*在预编译时将宏名替换成字符串的过程为:宏展开。
*#define 是宏定义命令 //求圆周长 #include <stdio.h> #define PI 3.1415926 int main( void ) { float r; //半径 float c; //周长 r= 3.0; c= 2* PI* r; //求圆周长 printf("%.3f\n", c ); //保留3为小数 return 0; }
PS:
(1) 宏名一般为大写字母表示,便于差别。但也能够是小写的
(2)使用宏名替换能够降低代码量。易于维护
(3) 宏定义不是C语句。所以不必在末尾加分号。假设加了分号,会宏名会替代字符串和分号
#define NUM 123; //有分号。编译器会报错!!
(4) 能够用#undef命令中止宏定义的作用域。否则其作用域由開始定义本文件结束。
//#undef的使用 #include<stdio.h> int main( void ) { #define N 20 //N替代20 printf( "%d\n", N ); #undef N //结束N的作用域。假设没有这条语句提示redefined #define N 30 //N替代 30 printf( "%d\n", N ); return 0; }
(5)宏定义时,能够引用已定义的宏名,能够层层置换
如:
#include<stdio.h> #define R 3.0 #define PI3.1415926 #define C2*PI*R #define SPI*R*R int main( void) { //打印圆的半径R。周长C,面积S printf( "R= %.2f\n", R ); printf( "C= %.2f\n", C ); printf( "S= %.2f\n", S ); return 0; }
(6)对于程序中有“”(双撇号括)括起来的字符串内的字符,即使与宏名同样,也不进行置换。
如:
#include<stdio.h> #define stringhello,world! #define STRING"hello,world!" int main( void ) { printf( "string" ); //string没有被替换为hello,world! putchar( ‘\n‘ ); //换行 printf( STRING ); //被替换为hello,world! return 0; }
执行结果:
string
hello,world!
(7) 宏定义有别于变量的定义。宏定义仅仅做字符替换,不分配存储空间
(b) 带參数的宏定义
作用:进行參数的替换
格式:#define宏名(參数表) 字符串
[ 1 ]ADD带參数的宏
#include <stdio.h> //带參数的宏替换 #define ADD( a, b ) ( (a)+ (b) ) //每一个变量使用括号是防止替换后有歧义 int main( void ) { int n= 10; int m= 20; int sum= 0; sum= ADD( n, m ); printf( "%d\n",sum ); return 0; }
[ 2 ]SIZEOF带參数的宏替换。
能够求数组的长度(记住sizeof的使用有限制!)
/* 使用说明: strlen()函数仅仅能求字符串的长度 sizeof不能求作为传递參数的数组原本的大小 */ #include <stdio.h> //定义SIZEOF宏 #define SIZEOF( array) ( sizeof( array )/ sizeof( array[ 0 ] ) ) int main( void ) { int num= 0; int array[]= { 1, 2,3, 3, 7, 22, 33, 44, 5, 5, 6, 7, 10 }; num= SIZEOF( array ); printf( "array的长度为%d\n",num ); return 0; }
执行结果:
array的长度为13
PS:
(1) 对于带參数的宏,按从左到有进行置换。假设字符串中的字符不是參数字符(如a+ b中的+)要保留。
(2) 在宏定义的宏名与參数的括号之间不能加空格,否则会被当作字符串的一部分
注意:函数与宏的差别
(1) 使用宏的次数多时,宏展开后程序的长度会增长;而函数的调用不会。
(2) 宏的替换不占用执行时间。仅仅占用编译时间。而函数则占用执行时间(即分配单元、值传递、返回等)
B: 文件包括”处理
“文件包括”处理:一个源文件能够将另外一个源文件的所有包括进来。
格式:(a)#include“文件名称”
(b)#include <文件名称>
两种格式的差别:使用尖括号表示在包括文件(即库文件)文件夹中去查找(包括文件夹是由用户在设置环境时设置),而不在源文件文件夹去查找;使用双引號则表示首先在当前的源文件文件夹中查找,若未找到才到包括文件夹(库文件)中去查找。
PS:
(1) 一个#include命令仅仅能包括一个源文件,多个源文件要多个#include的命令
(2) 假设文件1要包括文件2,而文件2要包括文件3,则能够在文件1中用两个#include命令分别包括文件2和文件3,并且文件3必须出如今文件2前。
(3) 文件包括能够嵌套使用。即一个包括文件能够包括一个被包括的文件
(4) 被包括文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。因此,假设file2.h中有全局静态变量,它也在file1.h文件里有效,不必用extern声明。
C:条件编译
条件编译:是对部分内容指定编译的条件,是其满足一定条件才进行编译。
格式:
(1)
#ifdef 标识符
程序段1
#else
程序段2
#endif
作用:假设标识符被#define定义过,就进行程序段1的编译;反之对程序段2进行编译。假设没有程序段2,能够对#else省略。
#include<stdio.h> #define R3.0 //定义R int main(void ) { #ifdef R //相似于if-else printf( "已经定义了R\n"); #else printf( "未定义R\n"); #endif //条件推断结束 return 0; }
(2)
#ifndef 标识符
程序段1
#else
程序段2
#endif
作用:假设标识符没有被#define定义过,则对程序段1进行编译;反之对程序段2进行编译。
(3)
#if 常量表达式
程序段1
#else
程序段2
#endif
作用:假设表达式的值为真(即非0)。则就对程序段1进行编译。反之对程序段2进行编译。
#include <stdio.h> #define R 3.0 //定义R int main( void ) { #ifndefR //相似于if-else printf("未定义了R\n" ); #else printf("已经有定义R\n" ); #endif //条件推断结束 return0; }
【指尖的微笑】错误在所难免,希望得到大家的指正^-^
转载时保留原文的链接http://oursharingclub.joinbbs.net/和http://blog.csdn.net/mirrorsbeyourself
C语言第十一回合:预处理命令的集中营