预处理-宏定义-条件编译

1、预处理之宏定义

可以用#define命令将一个指定的标识符(即宏名)来代表一个字符串;

宏定义语法:#define 宏名 字符串

使用原则:

1、“原样替换”;

2、不能代替函数;

3、定义时后缀不要加分号。

带参数的宏定义

#include <stdio.h>
#define s(a,b) a*b   //注意,此处不能加分号,否则就变成了s=(a*b;)
int main()
{
    printf("矩形1的面积是:%d\n",s(2,4));
    printf("矩形2的面积是:%f\n",s(1.2,1.2));
    return 0;
}

关于原样替换,请体会下面程序用法的错误

/*
*copyright(c) 2018,HH
*All rights reserved.
*作 者:HH
*完成日期:2018年08月05日
*版本号:v1.0
*
*问题描述:单参数的宏定义,“原样替换”
*输入描述:;
*程序输出:;
*/

#include <stdio.h>
#define pi 3.1415926
#define s(r) r*r*pi
//#define s(r) (r)*(r)*pi//正确的写法
int main()
{
    float a,b;
    a=1;
    b=2;
    printf("r=%f,圆形1的面积=%f\n",a+b,s(a+b));//1+2*1+2*3.1415926=1+2+6.2831852=9.2831852
    return 0;
}

 

2、预处理之“文件包含”

所谓“文件包含”处理是指一个源文件可以将另外一个源文件的全部内容包含进来。

源文件与头文件的分离,一般头文件包含以下几类内容:

1、对自定义类型的声明;

2、被调用函数的声明;

3、宏定义:用#define定义的符号常量和宏;

4、全局变量的定义;

5、外部变量的声明,例如:extern int a;

6、根据需要包含的其它头文件。

文件包含的作用:

“文件包含”命令可以节省程序设计人员的重复劳动,是模块化程序设计的产物,便于多个程序员分别编程;将公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用;公用的声明只写一次,除节省时间,更可观的是减少出错。

GCC编译器中的头文件和库函数

头文件:路径codeblocks/MinGW/include中包含.h的头文件;

库函数:路径codeblocks/MinGW/lib下的为.a的库函数(.o目标文件的集合)。

3、预处理之条件编译

/*
*copyright(c) 2018,HH
*All rights reserved.
*作 者:HH
*完成日期:2018年8月9日
*版本号:v1.0
*
*问题描:条件编译
*输入描述:;
*程序输出:
*/

#include <stdio.h>
#define debug//条件编译,“#define 标识符”,该语句如果之前加//则函数中语句会被自动注释
int main()
{
    int x=1,y=2;
#ifdef debug
    printf("x=%d y=%d\n",x,y);
#endif // debug
    printf("x*y=%d\n",x*y);
    return 0;
}

1)条件编译的常用形式之一

当所指定的标识符已经被#define命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。#endif用来限定#ifdef命令的范围,其中#else部分也可以没有。

#ifdef 标识符
    程序段1
# else
    程序段2
#endif


//当不需要编译程序端2时,可以写成如下形式:
#ifdef 标识符
    程序段1
#endif

当所指定的标识符没有被#define命令定义过,则在程序编译阶段只编译程序段1,否则编译程序段2。

#ifndef 标识符
    程序段1
#else
    程序段2
#endif

2)条件编译的常用形式之二

如常量表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能。

4、条件编译:避免重复编译

条件指示符#ifndef 的最主要目的是防止头文件的重复包含和编译。了解:条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。

#ifndef 标示1
    #define 标示1  
#endif
  程序段1

该段代码意思是:如果标示1没有被定义,则重定义标示1,然后在执行程序段1、……;如果标示1已经被定义,则直接跳过,直接执行程序端1。

备注:#ifndef 和 #endif 要一起使用,如果丢失#endif,可能会报错。

千万不要忽略了头文件中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识>
  #define <标识>
  ......
  ......
#endif

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前面加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

在c语言中,对同一个变量或者函数进行多次声明是不会报错的。所以如果h文件里只是进行了声明工作,即使不使用# ifndef宏定义,一个c文件多次包含同一个h文件也不会报错。

但是在c++语言中,#ifndef的作用域只是在单个文件中。所以如果h文件里定义了全局变量,即使采用#ifndef宏定义,一个c文件包含同一个h文件多次还是会出现全局变量重定义的错误。

使用#ifndef可以避免下面这种错误:如果在h文件中定义了全局变量,一个c文件包含同一个h文件多次,如果不加#ifndef宏定义,会出现变量重复定义的错误;如果加了#ifndef,则不会出现这种错误。

“ 条件编译”命令允许对程序中的内容选择性地编译,即可以根据一定的条件选择是否编译。

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值