黑马程序员---C语言学习笔记之预处理指令、宏和条件编译

来源:互联网 发布:淘宝不给发票怎么应对 编辑:程序博客网 时间:2024/05/16 06:17
------Java培训、Android培训、iOS培训、.Net培训--------

一、预处理指令的概念及分类


1.基本概念

以“#”号开头指令都称为【预处理指令】。如包含命令#include等。在源程序中这些命令都放在函数之外。而且一般都放在源文件的前面,他们称为【预处理部分】

 

所谓预处理是指在进行编译的第一道扫描(词法扫描和语法扫描)之前所做的工作,预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分做处理,处理完毕自动进入对源程序的编译。

C语言提供了多种预处理功能。如宏定义,文件包含,条件编译等。合理地使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。


二、宏的概念及无参宏定义方法


1.宏的概念

被定义为“宏”的标识符称为“宏名”,在编译预处理时,都用宏定义中的字符串取代换,这称为“宏代换”或“宏展开”

 例如 #define Row 10 //此处Row就是一个宏

 

宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。在C语言中,“宏”分为【有参宏】和【无参宏】

 

无参宏的宏名不带参数,其定义一般形式为:

 

#define标识符字符串

 

其中"#"表示这是一掉预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”位所定义的宏名。“字符串”可以使常熟,表达式、格式串等

 

例如:

//定义一个宏#define PI 3.1415926#define Area PI*4#include <stdio.h> int main(int argc, const char * argv[]){     printf("area = %0.4f",Area);//预处理时,Area会被替换成3.1415926*4    return 0;}

 

【注意】

1、宏定义式一个预处理指令,结尾不需要加“;

2、宏定义替换问题

例如:

//定义一个宏#define PI 3.1415926#define Sum a*b+2*b#include <stdio.h> int main(int argc, const char * argv[]){     int a = 2,b =3;        printf("a2*Sum+ 3*Sum =%0d\n",2*Sum+ Sum);//预处理时,2*Sum+ Sum会被替换成2*a*b+2*b+a*b+2*b = 30而不是2*(a*b+2*b) +(a*b+2*b) = 36.    printf("2*a*b+2*b+a*b+2*b = %d\n", 2*a*b+2*b+a*b+2*b);    printf("2*(a*b+2*b) +(a*b+2*b) = %d", 2*(a*b+2*b) +(a*b+2*b));    return 0;}


打印结果:

a2*Sum+ 3*Sum = 30

2*a*b+2*b+a*b+2*b = 30

2*(a*b+2*b) +(a*b+2*b) = 36


三、有参宏的定义和使用方法

1、有参宏的定义方法

C语言允许宏带有参数,在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数,对带参数的宏,在调用中,不仅要宏展开,而且要用实参取代替形参。

 

带参宏定义的一般形式为:

define 宏名(参数表字符串

例如:

//定义一个带参宏#define Add(x,y) x+y#include <stdio.h> int main(int argc, const char * argv[]){    printf("x + y = %d", Add(10, 20));    return 0;}


 

打印结果:

x + y = 30

 

2、注意事项

1)宏的形参之间可以出现空格,但是【宏名】和【形参】之间不能出现空格

例如:

#define Add (x,y) x+y //报错#define Sub(x, y) x + y //不报错 

2)在带参宏定义中,形式蚕食不分配内存单元,因此不必做类型定义,而宏调用中的实参有具体值,要用他们去代换形参,因此必须做类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”,而带参宏中,只是符号代表,不存在值传递的问题。

 

3)在宏定义中的形参是标识符,而宏调用的实参可以是表达式

 

4)在宏定义中,【字符串内的形参通常要用括号括起来】以避免出错,

例如:

 #define Mul(x,y) x*y  #include <stdio.h> int main(int argc, const char * argv[]){    int a = 2, b = 3;    printf("x + y = %d", Mul(a + b, a*b));    return 0;}


打印结果:

x + y = 20

 

期待结果:(2+3)*(2*3) =30,但是宏展开的时候替换成了2+3*2*3 = 20

因此【字符串内的形参通常要用括号括起来】以避免出错,

如下:

#define Mul(x,y) (x)*(y)  #include <stdio.h> int main(int argc, const char * argv[]){    int a = 2, b = 3;    printf("x + y = %d", Mul(a + b, a*b));    return 0;}

 

打印结果:

x + y = 30


四、typedef#define的区别

1typedef#define的区别

 

例如:

//定义一个宏#defineMYINT int*//给int型起一个别名typedef int* MYINT2; #include <stdio.h> int main(int argc, const char * argv[]){    //使用宏定义变量    int num = 20;    MYINT a, b;//a是一个指针,b是一个普通变量,在宏展开的时候替换为int *a,b   a = #       printf("a = %d\n",*a);    //b =#    //printf("b = %d\n",*b);//报错   b = num;    printf("b = %d\n",b);//打印结果b = 20    //使用别名定义变量,不是简单的替换字符串,而是给类型起了个别名    MYINT2 c, d;   c = #    //d = num; //报错    d = #  //不会报错    printf("c = %d",*c);    return 0;}


五、条件编译的概念及优点

1.为什么要使用条件编译?

1)按不同的条件取编译不同的程序部分,因而产生不同的目标代码文件,有利于程序的一直和调试

 

2)条件编译当然也可以用条件语句来实现,但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用了条件编译,则根据条件只编译其中的程序段1或程序段4,生成的目标程序较短。

 

2.条件编译

发生在预处理阶段,在编译前做的事情

【核心】:根据条件编译指定的代码

条件不同,编译的部分也不同,生成的目标文件(.o)大小也不同

#define score 89#include <stdio.h> int main(int argc, const char * argv[]){   /* intscore = 89;    //用if条件语句实现,编译后(.o)文件的大小是1,172 bytes    score /=10;     if (score < 6) {        printf("E");    } else if (score < 7) {        printf("D");    }    else if (score < 8) {        printf("C");    }    else if (score < 9) {        printf("B");    }    else{        printf("A");    }*///使用条件编译,(.o)文件 836 bytes#if score < 6 //此处不能使用普通变量,要用宏定义     printf("E");#elif score < 7     printf("D");#elif score < 8     printf("C");#elif score < 9     printf("B");#else     printf("A");#endif //这个必须有,有#if配对    return 0;}


 

3#ifdef用来判断某个宏是否定义

例如:

    int a = 0;#ifdef AMOS//检测宏DEBUG1是否定义,若果定义了,a=10,对应的#ifndef,如果没有定义    a = 10;#else    a = 100;#endif    printf("a = %d\n",a);


 

4、使用条件编译调试程序

 

#define AMOS 0#include <stdio.h>//使用条件编译调试程序 #if AMOS == 1//显示调试信息#define Log(format,...) printf(format,## __VA_ARGS__);#else//不显示调试信息#define Log(format,...)#endif   int main(int argc, const char * argv[]){    int a = 0;#ifdef DEBUG1 //检测宏DEBUG1是否定义,若果定义了,a=10,对应的#ifndef,如果没有定义    a = 10;#else    a = 100;#endif    Log("------------------>a = %d\n", a);   return 0;}


打印结果:

当AMOS = 1时:

------------------>a= 100

当AMOS = 0时:

没有打印任何信息



0 0
原创粉丝点击