14.预处理指令:以#开头的都是预处理指令。在源程序中这些命令都放在函数之外,而且一般都放在源文件前面,它们称之为预处理指令。 预处理:在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。 15.c语言提供预处理功能,如宏定义、文件包含、条件编译等。 16.宏的概念及无参宏定义方法 宏: C语言中我们自定义的特殊标示符,习惯大写 宏的定义: #define 宏名 宏字符串(可以是常量、变量、表达式) 注意:预处理指令,经常写在函数之前 宏不是一个语句,是一个预处理指令,所以不需要加分号结束 3、宏替换 源程序在编译之前,由预处理程序对我们写的源代码进行处理:会把源代码中所有出现 宏名 的地方一律使用 宏的字符串 去替换 4、注意事项: (1)习惯上红名用大写字母表示,以便于与变量区别,但也允许用小写字母 (2)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中更可以含任何字符,可以是常量,也可以说表达式,预处理程序对它不做任何检查。如有错误,只能在编译已被展开后的源程序时发现 (3)宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号一起置换 (4)宏定义必须写在函数之外,其作用域为宏定义命令祈祷源程序结束。如要终止其作用域可使用#undef命令。 */ #include <stdio.h> #define M 10 #define M1 y*y+3*y #define R 4 #define PI 3.14 #define AREA PI*R*R //嵌套定义 #define INT1 int #define P struct Person void test(){ printf("M = %d\n",M); } //#undefM //此处的作用是,取消宏定义 void test1(){ printf("test1 =%d\n",M); } int main(int argc, const char * argv[]) { int a[M+2]; //int a[12] printf("%d\n",M); //把M的值打印出来 int y = 3,result=0; result = 3*M1+2*M1-50; //错误的 // 3*(y*y+3*y)+2*(y*y+3*y)-50; // 54 +36 -50; // 40 //正确的 // 3*y*y+3*y+2*y*y+3*y-50; // 27 +9 +18 + 9 -50; // 13 printf("result =%d\n",result); //宏使用的注意事项 //1、宏是有作用域的 #undef 宏名 可以取消宏定义 test(); test1(); //2、在字符串中出现的宏名不会被替换 //3、宏可以嵌套定义 printf("%.2f\n",AREA); //4、使用宏其别名 INT1 a1; a1 = 10; printf("a1 =%d\n",a1); P{ int age; }; P p1 = {23}; return 0; } 17. 有参宏的定义和使用方法 宏的分类: 无参宏 #define M 10 有参宏 #define SUM(a) a+a 对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。 SUM(3) //不仅要a+a替换,而且还要把 实参3代入到 字符串中 注意事项: (1)宏的形参之间可以出现空格,但是宏名和形参之间不能出现空格 (2)在带参宏定义中,形式参数不分配内存单元,因此不必做类型定义,而宏调用中的实参有具体的值,要用他们去代换形参,因此必须做类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。 (3)在宏定义中的形参是标识符,而宏调用中的实参可以是表达式 (4)在宏定义中,字符串内的形参通常要用括号括起来以避免出错, (5)可以用宏定义多个语句
|