c语言-预处理指令
2015-09-12 14:37
232 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
预处理指令概述
在C语言中,多次会用到以“#”靠头的预处理命令,比如说包含命令#include,宏定义命令#define等 ,这是我们最常见的,在源程序中这些命令都是放在行数之外,他们都称为预处理部分。
宏定义
在c语言源程序中允许用一个表示服来表示一个字符串,我们称之为“宏”。被定义为“宏”的表示服称为“宏名”。在编译预处理的时候,程序会对所有出现的“宏名”都用宏定义的字符串去代换,这成为"宏展开“或者“宏代换”
无参宏定义
无参宏的宏名后面不带参数,其定义的一般形式为: #define 标识符 字符串
其中”#“表示这是一条预处理命令,凡是以”#“开头的均为预处理命令。”define“为宏定义命令。”标识符“为所定义的的宏名(同长用大写字母表示,以便区和变量区分)”字符串“可以是常量,表达式,和格式串等。
2.使用宏定义的优点
1)可提高源程序的可维护性
2)可提高源程序的可移植性
3)减少源程序中重复书写字符串的工作量
#define PI 3.1415926 //PI是宏名,3.1415926用来替换宏名的常数
main() {
foat radius,length,area,volume;
printf("Input a radius: ");
cscanf("%f",&radius);
length=2*PI*radius; //引用无参宏求周长
area=PI*radius*radius; //引用无参宏求面积
volume=PI*radius*radius*radius*3/4; //引用无参宏求体积
printf("length=%.2f,area=%.2f,volume=%.2f"n", length, area, volume);
}
3.无参宏的注意:
(1)宏名一般用大写字母表示,以示与变量区别。但这并非是规定。
(2)宏定义不是C语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。
(3)在宏展开时,预处理程序仅以按宏定义简单替换宏名,而不作任何检查。如果有错误,只能由编译程序在编译宏展开后的源程序时发现。
(4)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。
(5)在进行宏定义时,可以引用已定义的宏名 。
(6)对双引号括起来的字符串内的字符,即使与宏名同名,也不进行宏展开。
(7)可以用#undef命令终止宏定义的作用域
#define M 3.1415926
main( ){
printf("M");
}
上例中宏定义名M表示3.1415926,但是在printf语句后被括号括起来,因此此处不作宏代换,输出结果是一字符M输出。
应注意宏定义表示数据类型和用typedef定义数据类型说明符的区别
宏定义知识简单的字符串代换,在预处理完成时,而typedef是在编译时处理的,他不是简单的代换,而是对类型说明符的重新命名,被命名的标识符具有类型定义说明功能。
如例:
#define PIN1 int*
typedef (int)PIN2;
从形式上看两者相似,但实际运用中却不相同。
下面用PIN1,PIN2说明变量是就可以看出他们的区别
PIN1 a,b;在宏代换后变成
int *a,b;
表示a指向整形的指针变量,而b是整型变量
然而:
PIN2 a,b;
表示a,b都是整形指针变量,所以说两者有时候看似相同会有很大的区别,我们在运用中一定要格外小心,不然就会造成错误。
带参宏定义
c语言允许宏带有参数,在宏定义的参数成为形式参数,在宏调用中的参数称为实际参数,对带参数的宏,在调用中,不仅要宏展开,而且要用实参去替换形参。
带参宏的定义一般形式为:
#define 宏名(形参表)字符串
在字符串含有各个形参。
带参宏的调用一般形式为:
宏名(实参表);
举例:
#define MA(x) x*(x+1)
#include<stdio.h>
int main(){
int num1=2;
int num2=3;
printf("%d",MA(num1+num2));
return 0;
}
上例的程序中进行代餐宏定义,用宏名MA表示条件表达式x*(x+1),形参x出现在表达式中,程序的在后面进行调用
其展开形式为2+3*(2+3+1)
文件包含
文件包含是C预处理程序的另一个重要功能。
文件包含命令行的一般形式为:
#include"文件名"
在前面我们已多次用此命令包含过库函数的头文件。例如:
#include"stdio.h"
#include"math.h"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。
对文件包含命令还要说明以下几点:
包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的:
#include"stdio.h"
#include<math.h>
但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找;
使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。
一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
条件编译指令
条件编译指令将决定那些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。
1.#if指令
#if指令检测跟在关键字后的常量表达式。如果表达式为真,则编译后面的代码,直到出现#else、#elif或#endif为止;否则就不编译。
2.#endif指令
#endif用于终止#if预处理指令。
#define DEBUG 0
main()
{
#if DEBUG
printf("Debugging\n");
#endif
printf("Running\n");
}
由于程序定义DEBUG宏代表0,所以#if条件为假,不编译后面的代码直到#endif,所以程序直接输出Running。
如果去掉#define语句,效果是一样的。
3.#ifdef和#ifndef
#define DEBUG
main()
{
#ifdef DEBUG
printf("yes\n");
#endif
#ifndef DEBUG
printf("no\n");
#endif
}
#if defined等价于#ifdef; #if !defined等价于#ifndef
4.#else指令
#else指令用于某个#if指令之后,当前面的#if指令的条件不为真时,就编译#else后面的代码。#endif指令将中指上面的条件块。
#define DEBUG
main()
{
#ifdef DEBUG
printf("Debugging\n");
#else
printf("Not debugging\n");
#endif
printf("Running\n");
}
5.#elif指令
#elif预处理指令综合了#else和#if指令的作用。
#define TWO
main() {
#ifdef ONE
printf("1\n");
#elif defined TWO
printf("2\n");
#else
printf("3\n");
#endif
}
程序很好理解,最后输出结果是2。
6.其他一些标准指令
#error指令将使编译器显示一条错误信息,然后停止编译。
#line指令可以改变编译器用来指出警告和错误信息的文件号和行号。
#pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。
预处理指令概述
在C语言中,多次会用到以“#”靠头的预处理命令,比如说包含命令#include,宏定义命令#define等 ,这是我们最常见的,在源程序中这些命令都是放在行数之外,他们都称为预处理部分。
宏定义
在c语言源程序中允许用一个表示服来表示一个字符串,我们称之为“宏”。被定义为“宏”的表示服称为“宏名”。在编译预处理的时候,程序会对所有出现的“宏名”都用宏定义的字符串去代换,这成为"宏展开“或者“宏代换”
无参宏定义
无参宏的宏名后面不带参数,其定义的一般形式为: #define 标识符 字符串
其中”#“表示这是一条预处理命令,凡是以”#“开头的均为预处理命令。”define“为宏定义命令。”标识符“为所定义的的宏名(同长用大写字母表示,以便区和变量区分)”字符串“可以是常量,表达式,和格式串等。
2.使用宏定义的优点
1)可提高源程序的可维护性
2)可提高源程序的可移植性
3)减少源程序中重复书写字符串的工作量
#define PI 3.1415926 //PI是宏名,3.1415926用来替换宏名的常数
main() {
foat radius,length,area,volume;
printf("Input a radius: ");
cscanf("%f",&radius);
length=2*PI*radius; //引用无参宏求周长
area=PI*radius*radius; //引用无参宏求面积
volume=PI*radius*radius*radius*3/4; //引用无参宏求体积
printf("length=%.2f,area=%.2f,volume=%.2f"n", length, area, volume);
}
3.无参宏的注意:
(1)宏名一般用大写字母表示,以示与变量区别。但这并非是规定。
(2)宏定义不是C语句,所以不能在行尾加分号。否则,宏展开时,会将分号作为字符串的1个字符,用于替换宏名。
(3)在宏展开时,预处理程序仅以按宏定义简单替换宏名,而不作任何检查。如果有错误,只能由编译程序在编译宏展开后的源程序时发现。
(4)宏定义命令#define出现在函数的外部,宏名的有效范围是:从定义命令之后, 到本文件结束。通常,宏定义命令放在文件开头处。
(5)在进行宏定义时,可以引用已定义的宏名 。
(6)对双引号括起来的字符串内的字符,即使与宏名同名,也不进行宏展开。
(7)可以用#undef命令终止宏定义的作用域
#define M 3.1415926
main( ){
printf("M");
}
上例中宏定义名M表示3.1415926,但是在printf语句后被括号括起来,因此此处不作宏代换,输出结果是一字符M输出。
应注意宏定义表示数据类型和用typedef定义数据类型说明符的区别
宏定义知识简单的字符串代换,在预处理完成时,而typedef是在编译时处理的,他不是简单的代换,而是对类型说明符的重新命名,被命名的标识符具有类型定义说明功能。
如例:
#define PIN1 int*
typedef (int)PIN2;
从形式上看两者相似,但实际运用中却不相同。
下面用PIN1,PIN2说明变量是就可以看出他们的区别
PIN1 a,b;在宏代换后变成
int *a,b;
表示a指向整形的指针变量,而b是整型变量
然而:
PIN2 a,b;
表示a,b都是整形指针变量,所以说两者有时候看似相同会有很大的区别,我们在运用中一定要格外小心,不然就会造成错误。
带参宏定义
c语言允许宏带有参数,在宏定义的参数成为形式参数,在宏调用中的参数称为实际参数,对带参数的宏,在调用中,不仅要宏展开,而且要用实参去替换形参。
带参宏的定义一般形式为:
#define 宏名(形参表)字符串
在字符串含有各个形参。
带参宏的调用一般形式为:
宏名(实参表);
举例:
#define MA(x) x*(x+1)
#include<stdio.h>
int main(){
int num1=2;
int num2=3;
printf("%d",MA(num1+num2));
return 0;
}
上例的程序中进行代餐宏定义,用宏名MA表示条件表达式x*(x+1),形参x出现在表达式中,程序的在后面进行调用
其展开形式为2+3*(2+3+1)
文件包含
文件包含是C预处理程序的另一个重要功能。
文件包含命令行的一般形式为:
#include"文件名"
在前面我们已多次用此命令包含过库函数的头文件。例如:
#include"stdio.h"
#include"math.h"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。
在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。
对文件包含命令还要说明以下几点:
包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的:
#include"stdio.h"
#include<math.h>
但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找;
使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。
一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。
文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。
条件编译指令
条件编译指令将决定那些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。
1.#if指令
#if指令检测跟在关键字后的常量表达式。如果表达式为真,则编译后面的代码,直到出现#else、#elif或#endif为止;否则就不编译。
2.#endif指令
#endif用于终止#if预处理指令。
#define DEBUG 0
main()
{
#if DEBUG
printf("Debugging\n");
#endif
printf("Running\n");
}
由于程序定义DEBUG宏代表0,所以#if条件为假,不编译后面的代码直到#endif,所以程序直接输出Running。
如果去掉#define语句,效果是一样的。
3.#ifdef和#ifndef
#define DEBUG
main()
{
#ifdef DEBUG
printf("yes\n");
#endif
#ifndef DEBUG
printf("no\n");
#endif
}
#if defined等价于#ifdef; #if !defined等价于#ifndef
4.#else指令
#else指令用于某个#if指令之后,当前面的#if指令的条件不为真时,就编译#else后面的代码。#endif指令将中指上面的条件块。
#define DEBUG
main()
{
#ifdef DEBUG
printf("Debugging\n");
#else
printf("Not debugging\n");
#endif
printf("Running\n");
}
5.#elif指令
#elif预处理指令综合了#else和#if指令的作用。
#define TWO
main() {
#ifdef ONE
printf("1\n");
#elif defined TWO
printf("2\n");
#else
printf("3\n");
#endif
}
程序很好理解,最后输出结果是2。
6.其他一些标准指令
#error指令将使编译器显示一条错误信息,然后停止编译。
#line指令可以改变编译器用来指出警告和错误信息的文件号和行号。
#pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。
相关文章推荐
- ubuntu12.04 安装eclipse C++,并配置交叉编译工程
- C++基础知识
- [LeetCode] 036. Valid Sudoku (Easy) (C++)
- c++实现两个大整数相加(一)
- C++ <利用指针翻转字符串>
- C++程序中尽量避免#define
- C++中栈区 堆区 常量区
- C/C++常用头文件及函数汇总
- c++11——列表初始化
- C、C++: 引用、指针、实例、内存模型、namespace
- 一个c语言写的文件系统
- Effective C++ 条款47 请使用traits classes表现类型信息
- 【反思】一个价值两天的BUG,无论工作还是学习C语言的朋友都看看吧!
- 为什么C++编译器不支持模板头文件和实现代码分离的编译
- 一:c语言(数据类型和运算符)
- C 语言漫谈(一)
- 第二周项目1-C/C++语言中函数参数传递的三种方式
- C++于public、protected和private说明(From MSDN)
- C++ 容器Vector简介
- C++ NAN 异常处理