第7章 编译预处理 本章要求: 本章重点: 本章难点: 掌握用#define定义无参数宏和带有参数宏定义和调用方法;

Slides:



Advertisements
Similar presentations
C++语言程序设计教程 第5章 构造数据类型 第6章 C++程序的结构.
Advertisements

河內塔(Hanoi)問題.
电子成绩单项目实现.
计算学科的基本问题 本章首先介绍一个对问题进行抽象的典型实例——哥尼斯堡七桥问题。然后,通过“梵天塔”问题和“停机问题”分别介绍学科中的可计算问题和不可计算问题。从“梵天塔”问题再引出算法复杂性中的难解性问题、P类问题和NP类问题,证比求易算法,P=NP是否成立的问题。
“八皇后”问题 崔萌萌 吕金华.
项目五——校园一卡通程序功能模块化设计 5-1项目显示查询和退出函数设计.
孟子名言 1. 幼吾幼,以及人之幼。 2.天时不如地利, 。 3. ,威武不能屈。 4.得道者多助, 。 5.穷则独善其身, 。 6.
寡人之于国也 《孟子》.
C语言基础——指针的高级应用 Week 05.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
第一章 程序设计入门.
Introduction to the C Programming Language
高级语言程序设计 主讲人:陈玉华.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
C的發展史 C程式初體驗 C程式設計基本注意事項 上機實習課程
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
第4章 选择结构程序设计 4.1 选择结构和条件判断 4.2 用if语句实现选择结构 4.3关系运算符和关系表达式
If … else 選擇結構 P27.
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
Chap 2 用C语言编写程序 2.1 在屏幕上显示 Hello World! 2.2 求华氏温度 100°F 对应的摄氏温度
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
Function.
Object-Oriented Programming in C++ 第一章 C++的初步知识
前處理指令可以要求前處理器 (preprocessor) 在程式編譯之前,先進行加入其它檔案的內容、文字取代以及選擇性編譯等工作。
程序设计专题一 结构化程序设计与递归函数 主讲教师: 刘新国.
作弊是否很有诱惑性? 上堂课已经讲了 作业不一定在两个小时里都能完成 答疑没有一个人? 作弊是有记录的 心理系很多同学集体作弊,让人震惊
6 使用者函數 6.1 函數定義 宣告函數 呼叫函數 呼叫多個函數 6-6
算法的基本概念.
期中考试成绩分布 《程序设计》-2017年秋.
多维数组与指针 用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。 1. 多维数组元素的地址 先回顾多维数组的性质,可以认为二维数组是“数组的数组”,例 : 定义int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
第五章 C/C++及汇编语言的混合编程 5.1 ARM C/C++编译器 5.2 在C/C++程序中内嵌汇编指令
計數式重複敘述 for 迴圈 P
2.1 C语言的数据类型 2.2 常量与变量 2.3 变量赋初值 2.4 各类数值型数据间的混合运算 2.5 C语言的运算符和表达式
第5讲 结构化程序设计(Part II) 周水庚 2018年10月11日.
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第6章 预 处 理.
第九章 预处理命令.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
C语言复习2----函数.
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
Introduction to the C Programming Language
C语言程序设计 教案 崔武子制作
Oop8 function函式.
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
Chap 5 函数 5.1 计算圆柱体积 5.2 数字金字塔 5.3 复数运算.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
C语言程序设计 李祥 QQ:
第2章 认识C语言 教学要点 2. 1 项目二C语言程序识读 2 .2 项目三班级成绩排名 2 .3 知识链接 返回.
项目1 C程序设计起步 学习目标: 通过该项目你可以知道: C语言的用途。 C语言的基本符号和关键字。 C语言程序的结构及特点。
第2章 数据类型、运算符与表达式 本章要点: 基本数据类型 常量和变量 算术运算符和算术表达式 关系运算符和关系表达式
第6章 预 处 理.
第二章 类型、对象、运算符和表达式.
第2章 数据类型与表达式 学习目的与要求: 掌握C 语言的基本数据类型及使用方法 掌握C程序中常用的运算符和表达式 了解数据类型的转换.
Introduction to the C Programming Language
本节内容 函数嵌套调用的内存布局 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第3章 最简单的C程序设计 3.1 顺序程序设计举例 3.2 数据的表现形式及其运算 3.3 C语句 3.4 数据的输入输出.
第七章  数 组.
第18讲 从C到C++ 计算机与通信工程学院.
C/C++基礎程式設計班 陣列 講師:林業峻 CSIE, NTU 3/14, 2015.
Chap 10 函数与程序结构 10.1 圆形体积计算器 10.2 汉诺塔问题 10.3 长度单位转换 10.4 大程序构成.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
Q1(a) 小偉打算編寫一個程序。該程序把兩個44的表內的數字相加。表3內的數字是由表1和表2應格子內的數字相加而成。例如:
Introduction to the C Programming Language
隨機函數.
Presentation transcript:

第7章 编译预处理 本章要求: 本章重点: 本章难点: 掌握用#define定义无参数宏和带有参数宏定义和调用方法; 第7章 编译预处理 本章要求: 掌握用#define定义无参数宏和带有参数宏定义和调用方法; 掌握#include文件包含的使用方法; 了解条件编译的使用。 本章重点: 带参宏定义和使用方法、文件包含的使用 本章难点: 带参宏定义和使用方法

第7章 编译预处理 在C语言源程序中以“#”号开头的预处理命令都放在函数之外,一般都放在源文件的前面,它们称为预处理部分。 第7章 编译预处理 在C语言源程序中以“#”号开头的预处理命令都放在函数之外,一般都放在源文件的前面,它们称为预处理部分。 C语言提供了多种预处理功能,主要有宏定义、文件包含、条件编译。 宏定义命令(#define)、文件包含命令(#include)、条件编译命令(#if、#ifdef、#else、 # ifndef和#endif) 特点:用#开头,并且预处理命令单独占一行,不用分号。

7.1 宏定义 7.1.1 无参宏定义 例7-1 通过键盘输入50个实数,将其中大于它们平均值的数打印输出。(未使用宏定义) 7.1 宏定义 7.1.1 无参宏定义 例7-1 通过键盘输入50个实数,将其中大于它们平均值的数打印输出。(未使用宏定义) void main() { int i; float x[50], ave=0; for(i=0;i<50;i++) scanf("%f",&x[i]); ave+=x[i]; } ave=ave/50; if(x[i]>ave) printf("%f ",x[i]);

7.1 宏定义 7.1.1 无参宏定义 例7-2 通过键盘输入100个实数,将其中大于它们平均值的数打印输出。 (使用无参宏定义) 7.1 宏定义 7.1.1 无参宏定义 例7-2 通过键盘输入100个实数,将其中大于它们平均值的数打印输出。 (使用无参宏定义) #define NUM 100 void main() { int i;float x[NUM],ave=0; for(i=0;i<NUM;i++) { scanf("%f",&x[i]); ave+=x[i]; } ave=ave/NUM; if(x[i]>ave) printf("%f ",x[i]);

7.1 宏定义 7.1.1 无参宏定义 一般形式: #define 标识符 字符串 C语言源程序中用一个标识符来表示一个字符串, 称为宏。 7.1 宏定义 7.1.1 无参宏定义 一般形式: #define 标识符 字符串 C语言源程序中用一个标识符来表示一个字符串, 称为宏。 被定义为“宏”的标识符称为“宏名”。 在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,称为“宏代换”或“宏展开”。 宏定义是由源程序中的宏定义命令完成的。 宏代换是由预处理程序自动完成的。 C语言中,“宏”分为有参数和无参数两种。

7.1 宏定义 7.1.1 无参宏定义 例7-3 输入一个圆的半径,输出该圆的周长。 #define PI 3.14 7.1 宏定义 7.1.1 无参宏定义 例7-3 输入一个圆的半径,输出该圆的周长。 #define PI 3.14 #define C 2*PI*r /*PI是已定义的宏名*/ void main() { double r; printf("Enter The Radius\n"); scanf("%lf",&r); printf("The Perimeter=%lf\n",C); } printf("The Perimeter=%lf\n",2*PI*r); printf("The Perimeter=%lf\n",2*3.14*r);

7.1 宏定义 无参宏定义的说明: C语言允许宏定义嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理器进行层层代换。 7.1 宏定义 无参宏定义的说明: C语言允许宏定义嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理器进行层层代换。 本例的宏定义用“C”替换表达式“2*PI*r”,因此宏不仅可以代替常量,宏还可以表示任何字符串,甚至是整个表达式。 预处理器不能理解C语言,预处理时不检查语法,不分配内存空间,仅作简单字符串置换。源程序只有在进行编译时才作语法检查。

7.1.1 无参宏定义 使用无参数宏定义还有以下几点说明: 宏名遵守C语言标识符的命名规则。 宏定义必须写在函数之外,其作用域从定义开始到用#undef取消其定义或到文件结束为止。取消了符号常量和宏名约定以后,可以用命令#define重新定义它。 通常,#define命令写在文件的开头,函数之前,使其在本文件中全部有效。 宏定义的替换文本通常在同一行中,如果替换文本超过一行,必须在该行的最后加上反斜杠“\”,反斜杠表示替换文本继续到下一行。

7.1 宏定义 #define 7.1.2 带参宏定义 无参数宏用于定义符号来代替常量,C语言还允许用符号来定义操作。通过使用参数,可以创建外形和作用都与函数相似的类函数宏。 例7-5 用定义带参数宏来改写例7-3的程序。 #define PI 3.14 #define C(r) 2*PI*r /*PI是已定义的宏名*/ void main() { double radius,perimeter; printf("Enter The Radius\n"); scanf("%lf",&radius); perimeter=C(radius); printf("The Perimeter=%lf\n",perimeter); } 此处宏展开为: perimeter=2*3.14*radius;

7.1 宏定义 #define 7.1.2 带参宏定义 本例宏定义括号内的r称为形式参数,将宏调用时出现的变量名radius称为实际参数,形参和实参可以不止一个。 带参数宏定义的一般形式为: #define 宏名(形参表) 替换文本 带参宏调用的一般形式为: 宏名(实参表) 宏的参数用圆括号括起来,宏名与参数表间不能有空格,否则 将作为无参数宏来处理

7.1 宏定义 #define 说明: 带参宏定义中的形参是标识符,而宏调用中的实参可以是表达式。带参宏展开时,用实参字符串替换形参字符串,由于运算符的优先级问题,可能发生逻辑错误。可以采用给宏定义的形参加括号的方法来解决,用圆括号括住每个参数,并括住宏的整体定义。 例一,宏定义:#define S(r) 3.14*r*r 宏调用语句:area = S(a+b); 宏展开后:area =3.14*a+b*a+b; 例二,宏定义: #define S(r) 3.14*(r)*(r) 宏展开后:area =3.14*(a+b)*(a+b)

7.1.2 有参宏定义 7.1.3 带参宏与函数的比较 例7-7 使用函数来实现例7-5求圆周长的功能。 #define PI 3.14 7.1.3 带参宏与函数的比较 例7-7 使用函数来实现例7-5求圆周长的功能。 #define PI 3.14 double C(double r); void main() { double radius,per; printf("Enter The Radius\n"); scanf("%lf",&radius); per=C(radius); printf("The Perimeter=%lf\n",per); } double C(double r) { return 2*PI*r; 例7-5 用定义带参数宏来改写例7-3的程序。 #define PI 3.14 #define C(r) 2*PI*r void main() { double radius,per; printf("Enter The Radius\n"); scanf("%lf",&radius); per=C(radius); printf("The Perimeter=%lf\n",per); }

7.1.2 有参宏定义 7.1.3 带参宏与函数的比较 在例7-5的带参宏定义中,形式参数r不分配内存单元,因此不必作类型定义。宏调用中的实参radius有具体的值,宏展开时用它去代换形参r,因此必须作类型说明。 在本例的函数中,形参r和实参radius是两个不同的量,有各自的作用域,调用时要把实参值赋予形参,进行“值传递”。而带参宏只是简单的字符代换,不存在值传递的问题。

7.1.2 有参宏定义 函数调用和宏调用二者在形式上相似,在本质上是完全不同的。现将它们的区别归纳如表所示: 区别项目 函数 宏 信息传递 实参的值或地址传送给形参。 用实参的字符串替换形参。 处理时刻、内存分配情况 程序运行时处理,分配临时内存单元。 宏展开在预编译时处理,不存在分配内存的问题。 参数类型 实参和形参类型一致。如不一致,编译器进行类型转换。 作字符串替换,不存在参数类型问题。 返回值 可以有一个返回值。 作字符串替换,不存在返回值问题。 对源程序的影响 无影响。 宏展开后使程序加长。 时间占用 占用程序运行时间。 占用编译时间。

#include "文件名" 或:#include <文件名> 所谓“文件包含”,是指一个原文件可以将另外一个原文件的所有内容包含进来。其使用格式为: #include "文件名" 或:#include <文件名> 例如,在前面我们已多次用此命令包含过库函数的头文件: #include "stdio.h" /* 包含标准输入输出头文件*/ #include "math.h" /* 包含数学函数头文件*/ #include "string.h" /* 包含字符串处理函数头文件*/

7.2 文件包含命令 #include 文件包含命令的作用: 在被包含文件(头文件)中集中书写符号常量定义、宏定义或外部说明等。 在每个需要这些定义或者说的源程序文件开始,用文件包含命令将这个头文件包含到程序中。

7.3 条件编译 条件编译能够让程序员控制预处理命令的执行和程序代码的编译。也就是说,条件编译预处理命令告诉编译器:根据编译时的条件接受或者忽略代码块。 条件编译有三种形式: 1.第一种形式: #ifdef 标识符 程序段1 [#else 程序段2 ] #endif #ifdef命令说明:如果预处理器已经定义了标识符,则编译代码直到下一个#else或者#endif命令出现为止。如果有#else命令,那么,在未定义标识符时会编译#else和#endif之间的代码。

7.3 条件编译命令 例7-9 根据是否定义宏C,决定是计算圆周长还是圆面积。 #define PI 3.14 #define C(r) 2*PI*(r) void main() {double r,c,s; printf("Enter The Radius\n"); scanf("%lf",&r); #ifdef C c=C(r);printf("The perimeter=%lf\n",c); #else s=PI*r*r;printf("The Area=%lf\n",s); #endif } 因为存在第2行的宏定义,因此系统编译求圆周长的那一段程序,而求面积的那段程序就不编译。

7.3 条件编译命令 2.第二种形式: #ifndef 标识符 程序段1 [#else 程序段2 ] #endif 如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。 3.第三种形式: #if 表达式 程序段1 #else 程序段2 #endif #if命令后跟常量整数表达式,如表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进行编译。

7.3 条件编译命令 例 使用条件编译的第三种形式改写例7-9。 #define PI 3.14 #define C 1 例 使用条件编译的第三种形式改写例7-9。 #define PI 3.14 #define C 1 void main() { double r,c,s; printf("Enter The Radius\n");scanf("%lf",&r); #if C c=2*PI*r;printf("The perimeter=%lf\n",c); #else s=PI*r*r;printf("The Area=%lf\n",s); #endif } 第2行宏定义中,定义C为1,因此在条件编译时,常量表达式的值为真,故计算并输出圆周长。