C语言:第10章 预处理命令

合集下载

C语言中级教材培训课程—预处理

C语言中级教材培训课程—预处理

C 语言中级培训预处理的概念编译前编译预处理器语言中,以“#”开头的语句统称为编译预处理命令。

以“#”开始,末尾这些命令必须在一行的开头以“#”开始,末尾不加分号,并且每条命令独占一行不加分号,并且每条命令独占一行,以区别于一为什么要用” 预处理”最小原则丁”的方式,由语言之外的预处理命令或函数提供。

就连处理预处理命令的预处理器C语言的预处理命令“预处理”前的预处理//有的系统是/ ,如VC++什么是宏#define PI (3.1415926)宏定义指令宏名字符串宏定义为什么要用宏定义-文字名称比数字要容易理解得多,一个好的宏名可以望文知义。

120使用宏的弊端:使用宏定义时需要注意的要点:宏替换的弊端:#define PF(x)x*x()()()/*#define PF(x)(x)*(x)*//*#define PF(x)((x)*(x))*/main()注意替换时不求值,{只是字符串的原样替换int a=2,b=3,c;c=PF(a+b)/PF(a+1);printf("\nc=%d",c);}按第一种宏定义:c=a+b*a+b/a+1*a+1;按第二种宏定义:()()()();c=(a+b)*(a+b)/(a+1)*(a+1)按第三种宏定义:c=((a+b)*(a+b))/((a+1)*(a+1));多用括号就万事大吉了吗?2:在定义宏时不要为宏加分号。

#define assert(e)\续行符#define assert(e) \宏定义实例——无参宏定义举例宏定义实例——带参数的宏定义举例宏定义实例——用宏定义构建机制#ifdef AFXDLL #ifdef _AFXDLL{0000AfxSig end(AFX PMSG)0}\ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \函数调用和宏定义的区别宏定义和类型定义的区别struct student*struct student *st uct stude t请分析下面语句的含义(*((UINT1*)(_data_)))定义了一个带参宏,它能将参数强转成无符号字符类型的地址,再将该地址中的值取出。

C语言习题集(预处理命令篇)

C语言习题集(预处理命令篇)

第六章预处理命令6.1 选择题1.下面叙述中正确的是()。

A. 带参数的宏定义中参数是没有类型的B. 宏展开将占用程序的运行时间C. 宏定义命令是C语言中的一种特殊语句D. 使用#include命令包含的头文件必须以“.h”为后缀2.下面叙述中正确的是()。

A. 宏定义是C语句,所以要在行末加分号B. 可以使用#undef命令来终止宏定义的作用域C. 在进行宏定义时,宏定义不能层层嵌套D. 对程序中用双引号括起来的字符串内的字符,与宏名相同的要进行置换3.在“文件包含”预处理语句中,当#include后面的文件名用双引号括起时,寻找被包含文件的方式为()。

A. 直接按系统设定的标准方式搜索目录B. 先在源程序所在目录搜索,若找不到,再按系统设定的标准方式搜索C. 仅仅搜索源程序所在目录D. 仅仅搜索当前目录4.下面叙述中不正确的是()。

A. 函数调用时,先求出实参表达式,然后带入形参。

而使用带参的宏只是进行简单的字符替换B. 函数调用是在程序运行时处理的,分配临时的内存单元。

而宏展开则是在编译时进行的,在展开时也要分配内存单元,进行值传递C. 对于函数中的实参和形参都要定义类型,二者的类型要求一致,而宏不存在类型问题,宏没有类型D. 调用函数只可得到一个返回值,而用宏可以设法得到几个结果5.下面叙述中不正确的是()。

A. 使用宏的次数较多时,宏展开后源程序长度增长。

而函数调用不会使源程序变长B. 函数调用是在程序运行时处理的,分配临时的内存单元。

而宏展开则是在编译时进行的,在展开时不分配内存单元,不进行值传递C. 宏替换占用编译时间D. 函数调用占用编译时间6.下面叙述中正确的是( )。

A. 可以把define和if定义为用户标识符B. 可以把define定义为用户标识符,但不能把if定义为用户标识符C. 可以把if定义为用户标识符,但不能把define定义为用户标识符D. define和if都不能定义为用户标识符7.下面叙述中正确的是()。

C语言教学课件

C语言教学课件

{float x=67,y;
y=2*sin(x*PI/180) ;
printf(“y=%f” , y ) ;
}
29返回
第三章 数据类型、运算符与表达式
§3.3 整型数据
1、常量: 十进制 567 ,-789 ,0 八进制 0567, -0753 十六进制 0x567 , -0xa1
2、变量: int i , j ; i=10 ; j= -10 ;
1+2+3+……+100=5050 或 100+1+99+2+98+……+49+51+50= 100+49*100+50=表示算法)
起止框
输入/出框
处理框
流程线
判断框
连接点
注释框
17
第二章 算法
例2.1 计算265的平方根
开始
顺序结构 X=265
1970 B (取BCPL第一个字母)
1972 C (取BCPL第二个字母)
1978 标准C
1983 ANSI C
1987 87 ANSI C 1990 ISO C
7跳转
第一章 C语言概述
§1.2 C语言特点
1、简练、自由、结构化 (32个关键字、9种控制语句)
2、运算符丰富(附录Ⅲ)34种 3、数据结构丰富
22返回
第三章 数据类型、运算符与表达式
第三章 数据类型、运算符与表达式
§3.1
C的数据类型
基本类型
整型 实型 字符型 枚举型
单精度 双精度
C数据类型
构造类型 指针类型
数组型 结构体型 共用体型
空类型 void(无return的函数)

C语言的预处理命令有哪些?

C语言的预处理命令有哪些?

问:关于C语言中的预处理命令?答:我们可以在C源程序中插入传给编译程序的各种指令,这些指令被称为预处理器指令(等价于汇编语言中的伪指令),它们扩充了程序设计的环境。

现把常用的预处理命令总结如下:1. 预处理程序按照ANSI标准的定义,预处理程序应该处理以下12条指令:#if、#ifdef、#ifndef、#else、#elif、#endif、#define、#undef、#line、#error、#pragma、#include。

显然,所有的12个预处理指令都以符号#开始,,每条预处理指令必须独占一行。

2. #define#define指令定义一个标识符和一个串(也就是字符集),在源程序中发现该标识符时,都用该串替换之(原样替换,不要附加任何人为理解上的符号)。

这种标识符称为宏名字,相应的替换称为宏代换。

一般形式如下:#define macro-name char-sequence这种语句不用分号结尾。

宏名字和串之间可以有多个空格符,但串开始后只能以新行终止。

在C语言里宏定义只用来做的宏名替换,而不做语法检查的,因而它不是C语句,所以宏定义的语句结尾不需要加分号。

宏也在C里也叫预处理命令,因为宏是在程序编译前先进行字符替换的,所以叫预处理.例如:我们使用LEFT代表1,用RIGHT代表0,我们使用两个#define指令:#define LEFT 1#define RIGHT 0每当在源程序中遇到LEFT或RIGHT时,编译程序都用1或0替换。

定义一个宏名字之后,可以在其他宏定义中使用,例如:#define ONE 1#define TWO ONE+ONE#define THREE ONE+TWO宏代换就是用相关的串替代标识符。

因此,如果希望定义一条标准错误信息时,可以如下定义:#define ERROR_MS “Standard error on input \n”如果一个串长于一行,可在行尾用反斜线”\”续行,如下:#define LONG_STRING “This is a very very long \s tring that is used as an example”3. #error#error指令强制编译程序停止编译,它主要用于程序调试(放在错误的分支中,一旦进入错误的分支就显示该信息)。

第10章 预处理命令

第10章 预处理命令

第十章预处理命令所谓编译预处理是指,在对源程序进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码。

一、宏定义与符号常量在C语言中,“宏”分为无参数的宏(简称无参宏)和有参数的宏(简称有参宏)两种。

无参宏定义1.无参宏定义的一般格式#define 标识符字符串其中:“define”为宏定义命令;“标识符”为所定义的宏名,通常用大写字母表示,以便于与变量区别;“字符串”可以是常数、表达式、格式串等。

2.使用宏定义的优点(1)可提高源程序的可维护性(2)可提高源程序的可移植性(3)减少源程序中重复书写字符串的工作量例9.1 输入圆的半径,求圆的周长、面积和球的体积。

要求使用无参宏定义圆周率。

/*程序功能:输入圆的半径,求圆的周长、面积和球的体积。

*/#define PI 3.1415926 /*PI是宏名,3.1415926用来替换宏名的常数*/void main(){float radius,length,area,volume;printf("Input a radius: ");scanf("%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)在宏展开时,预处理程序仅以按宏定义简单替换宏名,而不作任何检查。

预处理命令与结构体练习题答案

预处理命令与结构体练习题答案

第11章结构体与共用体一、选择题(在下列各题的A)、B)、C)、D)四个选项中,只有一个选项是正确的,请将正确选项填涂在答题卡相应位置上。

)11.1 C语言结构体类型变量在程序运行期间A)TC环境在内存中仅仅开辟一个存放结构体变量地址的单元B)所有的成员一直驻留在内存中C)只有最开始的成员驻留在内存中D)部分成员驻留在内存中考生答案: 正确答案: B11.2 下列各数据类型不属于构造类型的是A)枚举型 B)共用型 C)结构型 D)数组型考生答案: 正确答案: A11.3 当说明一个结构体变量时系统分配给它的内存是A)各成员所需内存量的总和 B)结构中第一个成员所需内存量C)成员中占内存量最大者所需的容量 D)结构中最后一个成员所需内存量考生答案: 正确答案: A11.4 设有以下说明语句typedef struct{ int n;char ch[8];} PER;则下面叙述中正确的是A)PER 是结构体变量名 B)PER是结构体类型名C)typedef struct 是结构体类型 D)struct 是结构体类型名考生答案: 正确答案: B11.5 已知有如下定义:struct a{char x; double y;}data,*t;,若有t=&data,则对data 中的成员的正确引用是A)(*t).data.x B)(*t).x C)t->data.x D)t.data.x 考生答案: 正确答案: B11.6 以下程序的运行结果是#include "stdio.h"main(){ struct date{ int year,month,day; } today;printf("%d\n",sizeof(struct date));}A)6 B)8 C)10 D)12考生答案: 正确答案: A11.7 设有如下定义:struck sk{ int a;float b;} data;int *p;若要使P指向data中的a域,正确的赋值语句是A)p=&a; B)p=data.a; C)p=&data.a; D)*p=data.a; 考生答案: 正确答案: C11.8 以下对结构体类型变量的定义中,不正确的是A)typedef struct aa{ int n;float m;} AA;AA tdl;B)#define AA struct aaAA { int n;float m;} tdl;C)struct{ int n;float m;} aa;struct aa tdl;D)struct{ int n;float m;} tdl;考生答案: 正确答案: C11.9 若有下面的说明和定义struct test{ int ml; char m2; float m3;union uu { char ul[5]; int u2[2];} ua;} myaa;则sizeof(struct test )的值是A)12 B)16 C)14 D)9考生答案: 正确答案: A11.10 以下程序的输出是struct st{ int x; int *y;} *p;int dt[4]={ 10,20,30,40};struct st aa[4]={ 50,&dt[0],60,&dt[0],60,&dt[0],60,&dt[0]};main(){ p=aa;printf("%d\n",++(p->x));}A)10 B)11 C)51 D)60考生答案: 正确答案: C11.11 有以下程序:#include <stdio.h>union pw{ int i;char ch[2];}a;main(){ a.ch[0]=13;a.ch[1]=0;printf("%d\n",a.i);}程序的输出结果是A)13 B)14 C)208 D)209 考生答案: 正确答案: A11.12 已知学生记录描述为:struct student{ int no;char name[20],sex;struct{ int year,month,day;} birth;};struct student s;设变量s中的“生日”是“1984年11月12日”,对“birth”正确赋值的程序段是A)year=1984;month=11;day=12;B)s.year=1984;s.month=11;s.day=12;C)birth.year=1984;birth.month=11;birth.day=12;D)s.birth.year=1984;s.birth.month=11;s.birth.day=12;考生答案: 正确答案: D11.13 有如下定义struct person{char name[9];int age;};struct person class[10]={"John",17,"paul",19,"Mary",18,"Adam",16,};根据上述定义,能输出字母M的语句是A)printf("%c\n",class[3].name);B)printf("%c\n",class[3].name[1]);C)printf("%c\n",class[2].name[1]);D)printf("%c\n",class[2].name[0]);考生答案: 正确答案: B11.14 下列程序的输出结果是struct abc{ int a, b, c, s; };main(){ struct abc s[2]={{1,2,3},{4,5,6}}; int t;t=s[0].a+s[1].b;printf("%d\n",t);}A)5 B)6 C)7 D)8考生答案: 正确答案: B11.15 若有下面的说明和定义,则sizeof(struct aa)的值是struct aa{ int r1; double r2; float r3;union uu{char u1[5];long u2[2];}ua;} mya;A)30 B)29 C)24 D)22考生答案: 正确答案: D11.16 有以下结构体说明和变量的定义,且指针p指向变量a,指针q指向变量b。

CC++常用预处理指令

CC++常用预处理指令

CC++常⽤预处理指令 预处理是在编译之前的处理,⽽编译⼯作的任务之⼀就是语法检查,预处理不做语法检查。

预处理命令以符号“#”开头。

常⽤的预处理指令包括:宏定义:#define⽂件包含:#include条件编译:#if、#elif、#ifndef、#ifdef、#endif、#undef错误信息指令:#error#line指令布局控制:#pragma宏定义 宏定义⼜称为宏代换、宏替换,简称“宏”。

宏替换只作替换,不做计算,不做表达式求解。

宏定义分带参数的宏定义和不带参数的宏定义。

在带参数的宏定义,宏名和参数的括号间不能有空格。

宏定义不分配内存,变量定义分配内存。

宏展开不占运⾏时间,只占编译时间;函数调⽤占运⾏时间(分配内存、保留现场、值传递、返回值)。

出现在宏定义中的#运算符把跟在其后的参数转换成⼀个字符串,有时把这种⽤法的#称为字符串化运算符。

例如:#include<iostream>using namespace std;#define STR(n)"abcd"#nint main(){cout<<STR(6)<<endl;system("pause");return0;} 输出结果为: ##运算符⽤于把参数连接到⼀起,预处理程序把出现在##两侧的参数合并成⼀个符号。

例如:#include<iostream>using namespace std;#define STR(a,b,c) a##b##cint main(){cout<<STR(1,2,3)<<endl;system("pause");return0;} 输出结果为:⽂件包含 #include<⽂件名>称为标准⽅式,到系统头⽂件⽬录查找⽂件,#include"⽂件名"则先在当前⽬录(⽤户路径)查找,⽽后到系统头⽂件⽬录查找。

预编译处理

预编译处理

预编译处理【学习目标】◇理解编译预处理的概念。

◇了解宏定义的概念,掌握简单宏定义和带参数的宏定义的格式和使用方法。

◇了解文件包含的概念,掌握文件包含的格式和使用方法。

能在程序中合理使用#include预处理指令◇了解条件编译的概念,掌握条件编译的三种格式及其使用方法。

能在程序中合理使用#define, #if, #ifndef, #else, #undef, #elif等指令。

【重点和难点】重点:编译预处理的概念,简单的宏定义与文件包含指令的用法。

难点:带参宏定义,条件编译指令,会用条件指令解决文件的重复包含问题。

【学习方法指导】本章的内容比较简单,严格说来,它也不算是C++语言的组成部分。

但是,一般说来,任何程序都离不开预编译指令。

特别是文件包含指令和条件编译指令,应把它们搞清楚。

虽然可以用宏定义的方法定义常数,但推荐使用const语句定义常量。

在编程中,如果我们能恰当地运用条件编译,就可以提高程序运行的效率。

【知识点】宏定义;宏替换;简单的宏定义;带参数的宏定义;文件包含;条件编译第一节宏定义我们用C++进行编程的时候,可以在源程序中包括一些编译命令,以告诉编译器对源程序如何进行编译。

这些命令包括:宏定义、文件包含和条件编译,由于这些命令是在程序编译的时候被执行的,也就是说,在源程序编译以前,先处理这些编译命令,所以,我们也把它们称之为编译预处理,本章将对这方面的内容加以介绍。

实际上,编译预处理命令不能算是C++语言的一部分,但它扩展了C++程序设计的能力,合理地使用编译预处理功能,可以使得编写的程序便于阅读、修改、移植和调试。

预处理命令共同的语法规则如下:◇所有的预处理命令在程序中都是以"#"来引导如"#include "stdio.h""。

◇每一条预处理命令必须单独占用一行,如"#include "stdio.h" #include <stdlib.h>" 是不允许的。

c语言程序设计谭浩强第四版

c语言程序设计谭浩强第四版

c语言程序设计谭浩强第四版C语言程序设计是计算机科学与技术领域中非常重要的基础课程之一。

谭浩强教授所著的《C语言程序设计》自问世以来,以其通俗易懂的语言和丰富的实例,深受广大学生和编程爱好者的喜爱。

第四版在继承前三版优点的基础上,对内容进行了更新和完善,更加符合现代编程教育的需求。

第一章:C语言概述本章主要介绍了C语言的发展历程、特点以及C语言在计算机编程领域中的应用。

C语言以其高效、灵活和可移植性,成为系统编程、嵌入式开发等领域的首选语言。

第二章:C语言的基本概念本章详细讲解了C语言的基本组成元素,包括数据类型、变量、常量、运算符和表达式等。

这些是编写C程序的基础,也是理解程序逻辑的关键。

第三章:顺序结构程序设计顺序结构是最简单的程序结构,本章通过实例讲解了如何使用顺序结构编写程序,以及如何通过输入输出函数实现数据的交互。

第四章:选择结构程序设计本章介绍了条件语句if、switch等选择结构的使用,通过这些结构可以实现程序的分支逻辑,使程序能够根据不同的条件执行不同的代码块。

第五章:循环结构程序设计循环结构是程序设计中不可或缺的部分,本章详细讲解了for、while、do-while等循环语句的用法,以及如何使用循环结构实现重复操作。

第六章:数组数组是存储多个同类型数据的集合,本章介绍了一维数组和二维数组的定义、初始化和使用,以及如何通过数组实现数据的批量处理。

第七章:函数函数是程序模块化的基础,本章讲解了函数的定义、声明、调用以及参数传递机制,包括值传递和地址传递的区别和应用。

第八章:指针指针是C语言中非常强大的特性之一,本章详细介绍了指针的基本概念、指针与数组的关系、指针的运算以及指针在函数中的应用。

第九章:结构体与联合体本章介绍了如何使用结构体和联合体来定义复杂的数据类型,以及如何通过这些复合数据类型实现数据的组织和管理。

第十章:预处理命令预处理命令是C语言编译过程中的特殊指令,本章讲解了宏定义、文件包含、条件编译等预处理命令的用法。

精品课件-程序设计基础(C语言)(杨俊清)-第10章

精品课件-程序设计基础(C语言)(杨俊清)-第10章

第10章 文 件
typedef struct {
shortlevel; 的程度*/
unsigned flags; charfd; unsigned charhold; 读取字符*/ shortb size; unsigned char*buffer; 置*/ unsignedar *curp; unsigned istemp; short token;
if ((fp=fopen("file1","r"))==NULL) {
printf("cannot open this file\n"); exit(0); }
第10章 文 件
即先检查打开的操作有否出错,如果有错就在终端上输出 “cannot open this file”。exit函数的作用是关闭所有文 件,终止正在调用的过程。待用户检查出错误,修改后再运行。
第10章 文 件
第10章 文 件
10.1 文件概述 10.2 文件的读写 10.3 文件定位 习题
第10章 文 件
10.1 文 件 概 述 文件(file)是程序设计中一个重要的概念。所谓“文 件”,一般指存储在外部介质上数据的集合。一批数据是以文 件的形式存放在外部介质(如磁盘)上的。操作系统是以文件为 单位对数据进行管理的,也就是说,如果想找存在外部介质上 的数据,必须先按文件名找到所指定的文件,然后再从该文件 中读取数据。要向外部介质上存储数据,也必须先建立一个文 件(以文件名标识),才能向它输出数据。
第10章 文 件
说明: (1) 用“r”方式打开的文件只能用于向计算机输入而不 能用作向该文件输出数据,而且该文件应该已经存在。不能用 “r”方式打开一个并不存在的文件(即输入文件),否则出错。 (2) 用“w”方式打开的文件只能用于向该文件写数据 (即输出文件),而不能用来向计算机输入。如果原来不存在该 文件,则在打开时新建立一个以指定的名字命名的文件。如果 原来已存在一个以该文件名命名的文件,则在打开时将该文件 删去,然后重新建立一个新文件。 (3) 如果希望向文件末尾添加新的数据(不希望删除原有 数据),则应该用“a”方式打开。但此时该文件必须已存在, 否则将得到出错信息。打开时,位置指针移到文件末尾。

C语言程序设计课程标准

C语言程序设计课程标准

《C语言程序设计》课程标准一.课程性质和任务:本课程是中等职业学校电子技术应用专业的专业基础课程。

本课程的前序课程是《计算机应用基础》,后续课程为《单片机应用技能实训》。

本课程是一门实践性非常强的课程,不但要注重C语言程序设计基本知识的学习,更要注重程序设计技能的培养,使学生能够循序渐进地掌握C语言程序设计的技能,初步积累编程经验,打下良好的编程基础。

本课程的学习,对学生职业能力培养和职业素养养成起着主要的支撑作用,为学生职业生涯的发展奠定基础。

二、课程教学目标:本课程的课程目标是培养学生编程的基本职业能力,学生学习完本课程后应达到的具体能力目标为:1、知识水平教学目标学会利用常见的C程序开发工具的使用,掌握开发环境的配置,掌握常见菜单命令的使用以及整个窗口的布局设置。

掌握结构化或模块化程序设计技能,学会数组、函数、三大控制结构、结构体和共用体以及指针的使用。

为软件后期维护和管理提供必要的技术支持。

2、能力培养目标C语言程序设计的课程开设是从学生的角度出发,注重培养学生良好的动手实践习惯,注重培养学生严谨的行事风格,尤其注重挖掘学生的潜质,注重培养与社会接轨,培养学生具有踏实工作作风,良好的观察和思考能力强以及团队合作能力。

3、素质培养目标通过C语言程序设计课程的教学,应注重培养学生编程的品质量等职业意识,养成良好的工作方法、工作作风和职业道德。

三参考学时108学时。

四、课程学分6学分五、教学内容及基本要求第1章C语言概述了解C语言的特点掌握C程序的基本结构熟练掌握Turbo C集成环境中常用菜单的使用重点:C程序的基本结构、程序的开发环境和开发过程。

第2章数据类型、运算符与表达式了解C语言的数据类型的概念了解标识符、常量和变量的概念掌握C语言简单数据类型了解运算符和表达式的概念、掌握算术运算符和表达式掌握赋值运算符和赋值表达式掌握自增和自减运算掌握关系运算符和关系表达式掌握逻辑运算符和逻辑表达式掌握条件运算符了解条件表达式了解逗号运算符和逗号表达式了解数据类型的转换重点:C语言中的数据类型,C语言的常量和变量。

C语言的预处理程序与注释

C语言的预处理程序与注释

C语言的预处理程序与注释C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。

虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。

本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。

1、C语言的预处理程序ANSI标准定义的C语言预处理程序包括下列命令:#define #error #include #if#else #elif #endif #ifdef#ifndef #indef #line #pragma非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。

2、#define命令#define定义了一个标识符及一个串。

在源程序中每次遇到该标识符时,均以定义的串代换它。

ANSI标准将标识符定义为宏名,将替换过程称为宏替换。

命令的一般形式为:#define identifier string注意,该语句没有分号。

在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。

例如,如希望TURE取值1,FALSE取值0,可说明两个宏#define#define TURE 1#define FALSE 0这使得在源程序中每次遇到TURE或FALSE就用0或1代替。

例如,在屏幕上打印“012”:printf("%d%d%d",FALSE,TRUE,TRUE+1);宏名定义后,即可成为其它宏名定义中的一部分。

例如,下面代码定义了O NE、TWO及THREE的值。

#define ONE 1#define TWO ONE+ONE#define THREE ONE+TWO懂得宏替换仅仅是以串代替标识符这点很重要。

因此,如果希望定义一个标准错误信息,可编写如下代码:#define E_MS "standard error on input\n"printf(E_MS);编译程序遇到标识符E_MS时,就用“standard error on input\n”替换。

C语言三种预处理功能

C语言三种预处理功能
2、 带参宏一般用法
比如#define MAX(a,b) ((a)>(b)?(a):(b))则遇到 MAX(1+2,value)则会把它替换成: ((1+2)>(value)?(1+2):(value))注意事项和无参宏差不多。 但还是应注意
#define FUN(a) "a"
则,输入 FUN(345)会被替换成什么? 其实,如果这么写,无论宏的实参是什么,都不会影响其被替换成"a"的命运。也就是说, ""内的字符不被当成形参,即使它和一模一样。那么,你会问了,我要是想让这里输入 FUN(345)它就替换成"345"该怎么实现呢?请看下面关于#的用法
带参数
除了一般的字符串替换,还要做参数代换
格式: #define 宏名(参数表) 字符串
例如:
#define S(a,b) a*b area=S(3,2);//第一步被换为 area=a*b; ,第二步被换为 area=3*2;
(1)实参如果是表达式容易出问题
#define S(r) r*r area=S(a+b);//第一步换为 area=r*r;,第二步被换为 area=a+b*a+b;
值传递、返回值)。
冷门重点编辑
#define 用法
1、用无参宏定义一个简单的常量
#define LEN 12
这个是最常见的用法,但也会出错。比如下面几个知识点你会吗?可以看下:
(1)#define NAME "zhangyuncong" 程序中有"NAME"则,它会不会被替换呢? (2)#define 0x abcd 可以吗?也就是说,可不可以用不是标识符的字母替换成别的东 西? (3)#define NAME "zhang 这个可以吗? (4)#define NAME "zhangyuncong" 程序中有上面的宏定义,并且,程序里有句: NAMELIST 这样,会不会被替换成"zhangyuncong"LIST 四个题答案都是十分明确的。 第一个,""内的东西不会被宏替换。这一点应该大家都知道; 第二个,宏定义前面的那个必须是合法的用户标识符; 第三个,宏定义也不是说后面东西随便写,不能把字符串的两个""拆开; 第四个:只替换标识符,不替换别的东西。NAMELIST 整体是个标识符,而没有 NAME 标识符,所以不替换。 也就是说,这种情况下记住:#define 第一位置第二位置 (1) 不替换程序中字符串里的东西; (2) 第一位置只能是合法的标识符(可以是关键字); (3) 第二位置如果有字符串,必须把""配对; (4) 只替换与第一位置完全相同的标识符。 还有就是老生常谈的话:记住这是简单的替换而已,不要在中间计算结果,一定要替换出 表达式之后再算。

C语言预处理命令

C语言预处理命令

编译预处理作业
程序2: 程序 : # include <stdio.h> int square(int x) {return(x*x); } main() {int i=1; while(i<=5) printf("%d\n",square(i++)); }
编译预处理
文件包含 格式1: 格式1: 文件标识” #include “[d:][path] 文件标识” 按路径搜索….h文件,若找不到, .h文件 按路径搜索 .h文件,若找不到,则按 系统指定的目录搜索。 系统指定的目录搜索。 格式2: 格式2: <头文件名 头文件名> #include <头文件名> 仅按系统指定的目录搜索。 仅按系统指定的目录搜索。Turbo C 默 认为tc include目录 VC安装路径下 tc\ 目录。 认为tc\include目录。VC安装路径下 的include 目录
编译预处理
对语句a=SQARE(n+1) 对语句a=SQARE(n+1) 1、将替换为a=n+1*n+1; 将替换为a=n+1*n+1; 2、将替换为a=(n+1)*(n+1); 将替换为a=(n+1)*(n+1); 将替换为a=((n+1)*(n+1)); 3、将替换为a=((n+1)*(n+1)); 对语句a=2.7/SQARE(3.0) 对语句a=2.7/SQARE(3.0) 将替换为a=2.7/(3.0)*(3.0); 2、将替换为a=2.7/(3.0)*(3.0); 将替换为a=2.7/((3.0)*(3.0)); 3、将替换为a=2.7/((3.0)*(3.0));

C语言中的预编译宏定义

C语言中的预编译宏定义

C语言中的预编译宏定义C语言中的预编译宏定义导语:C初学者可能对预处理器没什么概念,这是情有可原,下面是C中的预编译宏定义,一起来学习下吧:(一) 预处理命令简介预处理命令由#(hash字符)开头, 它独占一行, #之前只能是空白符. 以#开头的语句就是预处理命令, 不以#开头的语句为C中的代码行. 常用的预处理命令如下:#define 定义一个预处理宏#undef 取消宏的定义#include 包含文件命令#include_next 与#include相似, 但它有着特殊的用途#if 编译预处理中的条件命令, 相当于C语法中的if语句#ifdef 判断某个宏是否被定义, 若已定义, 执行随后的语句#ifndef 与#ifdef相反, 判断某个宏是否未被定义#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif 之后的语句, 相当于C语法中的else-if#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else 之后的语句, 相当于C语法中的else#endif #if, #ifdef, #ifndef这些条件命令的结束标志.defined 与#if, #elif配合使用, 判断某个宏是否被定义#line 标志该语句所在的行号# 将宏参数替代为以参数值为内容的字符窜常量## 将两个相邻的标记(token)连接为一个单独的标记#pragma 说明编译器信息#warning 显示编译警告信息#error 显示编译错误信息(二) 预处理的文法预处理并不分析整个源代码文件, 它只是将源代码分割成一些标记(token), 识别语句中哪些是C语句, 哪些是预处理语句. 预处理器能够识别C标记, 文件名, 空白符, 文件结尾标志.预处理语句格式: #command name(...) token(s)1, command预处理命令的名称, 它之前以#开头, #之后紧随预处理命令, 标准C允许#两边可以有空白符, 但比较老的编译器可能不允许这样. 若某行中只包含#(以及空白符), 那么在标准C中该行被理解为空白. 整个预处理语句之后只能有空白符或者注释, 不能有其它内容.2, name代表宏名称, 它可带参数. 参数可以是可变参数列表(C99).3, 语句中可以利用""来换行.e.g.# define ONE 1 /* ONE == 1 */等价于: #define ONE 1#define err(flag, msg) if(flag)printf(msg)等价于: #define err(flag, msg) if(flag) printf(msg)(三) 预处理命令详述1, #define#define命令定义一个宏:#define MACRO_NAME(args) tokens(opt)之后出现的MACRO_NAME将被替代为所定义的标记(tokens). 宏可带参数, 而后面的标记也是可选的.对象宏不带参数的宏被称为"对象宏(objectlike macro)"#define经常用来定义常量, 此时的宏名称一般为大写的字符串. 这样利于修改这些常量.e.g.#define MAX 100int a[MAX];#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endif#define __FILE_H__ 中的宏就不带任何参数, 也不扩展为任何标记. 这经常用于包含头文件.要调用该宏, 只需在代码中指定宏名称, 该宏将被替代为它被定义的内容.函数宏带参数的宏也被称为"函数宏". 利用宏可以提高代码的运行效率: 子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源. 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率.函数宏的参数是固定的情况函数宏的定义采用这样的方式: #define name( args ) tokens其中的args和tokens都是可选的. 它和对象宏定义上的区别在于宏名称之后不带括号.注意, name之后的左括号(必须紧跟name, 之间不能有空格, 否则这就定义了一个对象宏, 它将被替换为以(开始的字符串. 但在调用函数宏时, name与(之间可以有空格.e.g.#define mul(x,y) ((x)*(y))注意, 函数宏之后的参数要用括号括起来, 看看这个例子:e.g.#define mul(x,y) x*y"mul(1, 2+2);" 将被扩展为: 1*2 + 2同样, 整个标记串也应该用括号引用起来:e.g.#define mul(x,y) (x)*(y)sizeof mul(1,2.0) 将被扩展为 sizeof 1 * 2.0调用函数宏时候, 传递给它的参数可以是函数的返回值, 也可以是任何有意义的语句:e.g.mul (f(a,b), g(c,d));e.g.#define (stmt) stmt( a=1; b=2;) 相当于在代码中加入 a=1; b=2 .( a=1, b=2;) 就有问题了: 预处理器会提示出错: 函数宏的参数个数不匹配. 预处理器把","视为参数间的分隔符.((a=1, b=2;)) 可解决上述问题.在定义和调用函数宏时候, 要注意一些问题:1, 我们经常用{}来引用函数宏被定义的内容, 这就要注意调用这个函数宏时的";"问题.example_3.7:#define swap(x,y) { unsigned long _temp=x; x=y; y=_tmp}如果这样调用它: "swap(1,2);" 将被扩展为: { unsigned long _temp=1; 1=2; 2=_tmp};明显后面的;是多余的, 我们应该这样调用: swap(1,2)虽然这样的调用是正确的, 但它和C语法相悖, 可采用下面的方法来处理被{}括起来的内容:#define swap(x,y)do { unsigned long _temp=x; x=y; y=_tmp} while (0)swap(1,2); 将被替换为:do { unsigned long _temp=1; 1=2; 2=_tmp} while (0);在Linux内核源代码中对这种do-while(0)语句有这广泛的应用.2, 有的函数宏是无法用do-while(0)来实现的, 所以在调用时不能带上";", 最好在调用后添加注释说明.eg_3.8:#define incr(v, low, high)for ((v) = (low),; (v) <= (high); (v)++)只能以这样的形式被调用: incr(a, 1, 10) /* increase a form 1 to 10 */函数宏中的参数包括可变参数列表的情况C99标准中新增了可变参数列表的内容. 不光是函数, 函数宏中也可以使用可变参数列表.#define name(args, ...) tokens#define name(...) tokens"..."代表可变参数列表, 如果它不是仅有的'参数, 那么它只能出现在参数列表的最后. 调用这样的函数宏时, 传递给它的参数个数要不少于参数列表中参数的个数(多余的参数被丢弃).通过__VA_ARGS__来替换函数宏中的可变参数列表. 注意__VA_ARGS__只能用于函数宏中参数中包含有"..."的情况.e.g.#ifdef DEBUG#define my_printf(...) fprintf(stderr, __VA_ARGS__)#else#define my_printf(...) printf(__VA_ARGS__)#endiftokens中的__VA_ARGS__被替换为函数宏定义中的"..."可变参数列表.注意在使用#define时候的一些常见错误:#define MAX = 100#define MAX 100;=, ; 的使用要值得注意. 再就是调用函数宏是要注意, 不要多给出";".注意: 函数宏对参数类型是不敏感的, 你不必考虑将何种数据类型传递给宏. 那么, 如何构建对参数类型敏感的宏呢? 参考本章的第九部分, 关于"##"的介绍.关于定义宏的另外一些问题(1) 宏可以被多次定义, 前提是这些定义必须是相同的. 这里的"相同"要求先后定义中空白符出现的位置相同, 但具体的空白符类型或数量可不同, 比如原先的空格可替换为多个其他类型的空白符: 可为tab, 注释...e.g.#define NULL 0#define NULL /* null pointer */ 0上面的重定义是相同的, 但下面的重定义不同:#define fun(x) x+1#define fun(x) x + 1 或: #define fun(y) y+1如果多次定义时, 再次定义的宏内容是不同的, gcc会给出"NAME redefined"警告信息.应该避免重新定义函数宏, 不管是在预处理命令中还是C语句中, 最好对某个对象只有单一的定义. 在gcc中, 若宏出现了重定义, gcc会给出警告.(2) 在gcc中, 可在命令行中指定对象宏的定义:e.g.$ gcc -Wall -DMAX=100 -o tmp tmp.c相当于在tmp.c中添加" #define MAX 100".那么, 如果原先tmp.c中含有MAX宏的定义, 那么再在gcc调用命令中使用-DMAX, 会出现什么情况呢?---若-DMAX=1, 则正确编译.---若-DMAX的值被指定为不为1的值, 那么gcc会给出MAX宏被重定义的警告, MAX的值仍为1.注意: 若在调用gcc的命令行中不显示地给出对象宏的值, 那么gcc 赋予该宏默认值(1), 如: -DVAL == -DVAL=1(3) #define所定义的宏的作用域宏在定义之后才生效, 若宏定义被#undef取消, 则#undef之后该宏无效. 并且字符串中的宏不会被识别e.g.#define ONE 1sum = ONE + TWO /* sum = 1 + TWO */#define TWO 2sum = ONE + TWO /* sum = 1 + 2 */#undef ONEsum = ONE + TWO /* sum = ONE + 2 */char c[] = "TWO" /* c[] = "TWO", NOT "2"! */(4) 宏的替换可以是递归的, 所以可以嵌套定义宏.e.g.# define ONE NUMBER_1# define NUMBER_1 1int a = ONE /* a = 1 */2, #undef#undef用来取消宏定义, 它与#define对立:#undef name如够被取消的宏实际上没有被#define所定义, 针对它的#undef 并不会产生错误.当一个宏定义被取消后, 可以再度定义它.3, #if, #elif, #else, #endif#if, #elif, #else, #endif用于条件编译:#if 常量表达式1语句...#elif 常量表达式2语句...#elif 常量表达式3语句......#else语句...#endif#if和#else分别相当于C语句中的if, else. 它们根据常量表达式的值来判别是否执行后面的语句. #elif相当于C中的else-if. 使用这些条件编译命令可以方便地实现对源代码内容的控制.else之后不带常量表达式, 但若包含了常量表达式, gcc只是给出警告信息.使用它们可以提升代码的可移植性---针对不同的平台使用执行不同的语句. 也经常用于大段代码注释.e.g.#if 0{一大段代码;}#endif常量表达式可以是包含宏, 算术运算, 逻辑运算等等的合法C常量表达式, 如果常量表达式为一个未定义的宏, 那么它的值被视为0.#if MACRO_NON_DEFINED == #if 0在判断某个宏是否被定义时, 应当避免使用#if, 因为该宏的值可能就是被定义为0. 而应当使用下面介绍的#ifdef或#ifndef.注意: #if, #elif, #else之后的宏只能是对象宏. 如果name为名的宏未定义, 或者该宏是函数宏. 那么在gcc中使用"-Wundef"选项会显示宏未定义的警告信息.4, #ifdef, #ifndef, defined.#ifdef, #ifndef, defined用来测试某个宏是否被定义#ifdef name 或 #ifndef name它们经常用于避免头文件的重复引用:#ifndef __FILE_H__#define __FILE_H__#include "file.h"#endifdefined(name): 若宏被定义,则返回1, 否则返回0.它与#if, #elif, #else结合使用来判断宏是否被定义, 乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef. defined用于在一条判断语句中声明多个判别条件:#if defined(VAX) && defined(UNIX) && !defined(DEBUG)和#if, #elif, #else不同, #indef, #ifndef, defined测试的宏可以是对象宏, 也可以是函数宏. 在gcc中使用"-Wundef"选项不会显示宏未定义的警告信息.5, #include , #include_next#include用于文件包含. 在#include 命令所在的行不能含有除注释和空白符之外的其他任何内容.#include "headfile"#include#include 预处理标记前面两种形式大家都很熟悉, "#include 预处理标记"中, 预处理标记会被预处理器进行替换, 替换的结果必须符合前两种形式中的某一种.实际上, 真正被添加的头文件并不一定就是#include中所指定的文件. #include"headfile"包含的头文件当然是同一个文件, 但#include 包包含的"系统头文件"可能是另外的文件. 但这不值得被注意. 感兴趣的话可以查看宏扩展后到底引入了哪些系统头文件.关于#include "headfile"和#include 的区别以及如何在gcc中包含头文件的详细信息, 参考本blog的GCC笔记.相对于#include, 我们对#include_next不太熟悉. #include_next 仅用于特殊的场合. 它被用于头文件中(#include既可用于头文件中, 又可用于.c文件中)来包含其他的头文件. 而且包含头文件的路径比较特殊: 从当前头文件所在目录之后的目录来搜索头文件.比如: 头文件的搜索路径一次为A,B,C,D,E. #include_next所在的当前头文件位于B目录, 那么#include_next使得预处理器从C,D,E目录来搜索#include_next所指定的头文件.可参考cpp手册进一步了解#include_next6, 预定义宏标准C中定义了一些对象宏, 这些宏的名称以"__"开头和结尾, 并且都是大写字符. 这些预定义宏可以被#undef, 也可以被重定义.下面列出一些标准C中常见的预定义对象宏(其中也包含gcc自己定义的一些预定义宏:__LINE__ 当前语句所在的行号, 以10进制整数标注.__FILE__ 当前源文件的文件名, 以字符串常量标注.__DATE__ 程序被编译的日期, 以"Mmm dd yyyy"格式的字符串标注.__TIME__ 程序被编译的时间, 以"hh:mm:ss"格式的字符串标注, 该时间由asctime返回.__STDC__ 如果当前编译器符合ISO标准, 那么该宏的值为1__STDC_VERSION__ 如果当前编译器符合C89, 那么它被定义为199409L, 如果符合C99, 那么被定义为199901L.我用gcc, 如果不指定-std=c99, 其他情况都给出__STDC_VERSION__未定义的错误信息, 咋回事呢?__STDC_HOSTED__ 如果当前系统是"本地系统(hosted)", 那么它被定义为1. 本地系统表示当前系统拥有完整的标准C库.gcc定义的预定义宏:__OPTMIZE__ 如果编译过程中使用了优化, 那么该宏被定义为1.__OPTMIZE_SIZE__ 同上, 但仅在优化是针对代码大小而非速度时才被定义为1.__VERSION__ 显示所用gcc的版本号.可参考"GCC the complete reference".要想看到gcc所定义的所有预定义宏, 可以运行: $ cpp -dM /dev/null7, #line#line用来修改__LINE__和__FILE__.e.g.printf("line: %d, file: %s ", __LINE__, __FILE__);#line 100 "haha"printf("line: %d, file: %s ", __LINE__, __FILE__);printf("line: %d, file: %s ", __LINE__, __FILE__);显示:line: 34, file: 1.cline: 100, file: hahaline: 101, file: haha8, #pragma, _Pragma#pragma用编译器用来添加新的预处理功能或者显示一些编译信息. #pragma的格式是各编译器特定的, gcc的如下:#pragma GCC name token(s)#pragma之后有两个部分: GCC和特定的pragma name. 下面分别介绍gcc中常用的.(1) #pragma GCC dependencydependency测试当前文件(既该语句所在的程序代码)与指定文件(既#pragma语句最后列出的文件)的时间戳. 如果指定文件比当前文件新, 则给出警告信息.e.g.在demo.c中给出这样一句:#pragma GCC dependency "temp-file"然后在demo.c所在的目录新建一个更新的文件: $ touch temp-file, 编译: $ gcc demo.c 会给出这样的警告信息: warning: current file is older than temp-file如果当前文件比指定的文件新, 则不给出任何警告信息.还可以在在#pragma中给添加自定义的警告信息.e.g.#pragma GCC dependency "temp-file" "demo.c needs to be updated!"1.c:27:38: warning: extra tokens at end of #pragma directive1.c:27:38: warning: current file is older than temp-file注意: 后面新增的警告信息要用""引用起来, 否则gcc将给出警告信息.(2) #pragma GCC poison token(s)若源代码中出现了#pragma中给出的token(s), 则编译时显示警告信息. 它一般用于在调用你不想使用的函数时候给出出错信息.e.g.#pragma GCC poison scanfscanf("%d", &a);warning: extra tokens at end of #pragma directiveerror: attempt to use poisoned "scanf"注意, 如果调用了poison中给出的标记, 那么编译器会给出的是出错信息. 关于第一条警告, 我还不知道怎么避免, 用""将token(s)引用起来也不行.(3) #pragma GCC system_header从#pragma GCC system_header直到文件结束之间的代码会被编译器视为系统头文件之中的代码. 系统头文件中的代码往往不能完全遵循C标准, 所以头文件之中的警告信息往往不显示. (除非用#warning显式指明).(这条#pragma语句还没发现用什么大的用处)由于#pragma不能用于宏扩展, 所以gcc还提供了_Pragma:e.g.#define PRAGMA_DEP #pragma GCC dependency "temp-file"由于预处理之进行一次宏扩展, 采用上面的方法会在编译时引发错误, 要将#pragma语句定义成一个宏扩展, 应该使用下面的_Pragma语句:#define PRAGMA_DEP _Pragma("GCC dependency "temp-file"")注意, ()中包含的""引用之前引该加上转义字符.9, #, ###和##用于对字符串的预处理操作, 所以他们也经常用于printf, puts之类的字符串显示函数中.#用于在宏扩展之后将tokens转换为以tokens为内容的字符串常量.e.g.#define TEST(a,b) printf( #a "<" #b "=%d ", (a)<(b));注意: #只针对紧随其后的token有效!##用于将它前后的两个token组合在一起转换成以这两个token 为内容的字符串常量. 注意##前后必须要有token.e.g.#define TYPE(type, n) type n之后调用:TYPE(int, a) = 1;TYPE(long, b) = 1999;将被替换为:int a = 1;long b = 1999;(10) #warning, #error#warning, #error分别用于在编译时显示警告和错误信息, 格式如下:#warning tokens#error tokense.g.#warning "some warning"注意, #error和#warning后的token要用""引用起来!(在gcc中, 如果给出了warning, 编译继续进行, 但若给出了error, 则编译停止. 若在命令行中指定了 -Werror, 即使只有警告信息, 也不编译.【C语言中的预编译宏定义】。

C语言习题册答案集

C语言习题册答案集

第1章绪论一、选择题1~5 CABCD 6~10 BDCBC 11~15 AADCC二、程序填空题1、一个C语言程序是由函数组成的。

2、C源程序的后缀名为___.c_____3、在C程序中,main()函数最多有 1 个。

4、一个C语言程序总是从主函数/main( ) 开始执行。

5、在C语言里输入是由 scanf 函数实现,输出是由 printf 函数实现。

6、C语言中,当复合语句多于一条时,要求有一对 { } 括号。

7、一个C源程序必须经过_ 编译__和_链接__生成exe文件才能运行8、在一个C程序中注释部分两侧的分界符分别为_/*_____和_*/___9、编写计算机所程序所使用的语言称为__程序设计语言______。

10、程序设计语言的发展经历了三个阶段__机器语言__、_汇编语言_和__高级语言__第2章基本数据类型及顺序结构程序设计一、选择题01~05 ACDDA 06~10 ACAAC 11~15 BDBBC16~20 DABAA 21~25 DBDAA 26~30 ADDCB31~35 BDCAB二、程序填空题1、__基本数据类型、_构造类型___ 和___其它类型_______。

2、 4 、 4 、 8 、 1 。

3、 double4、 x<-5||x>5或 abs(x)>55、 y%2==1 或y%2!=06、 x%3==0&&x%7==0或x%21==0 ,7、 10 , 10 。

8、printf(“****a=%d, b=%d****”,a,b) 。

9、a:b ; c:t1 ;10、 x%10 , x/10%10 ;三、程序阅读题1、 G 。

2、 2, 1 。

3、 0 。

4、 16 。

5、2,50 。

6、 b 。

7、 3 。

8、10,20,0 。

9、 2, 20.00 。

10、67, e 。

第3章分支结构一、选择题01-05:DCBCD 06-10:CBBBC 11-15:CBBDB16-20:ACDAA 21-25:CADBC 26-30:CBBAD二、程序阅读题(共10题)1、 20,0 。

预处理命令

预处理命令

预处理命令预处理命令的作用:对源程序编译之前做一些处理,生成扩展C源程序。

可以简化程序开发过程,提高程序的可读性,也更有利于移植和调试C语言程序。

一、宏定义1.不带参数的宏定义(1)格式:#define 宏名标识符宏内容字符序列(2)说明:①“#”开头;②占单独书写行;③行的尾部不以分号作为结束标记。

(3)宏展开(即宏替换)在用“宏内容字符序列”替换“宏名标识符”时,必须原样替换。

例如,有程序:#define NUM1 10#define NUM2 20#define NUM NUM1 + NUM2 main ( ){int a=2, b=3;a*=NUM; b=b*NUM;printf("a=%d, b=%d\n",a,b); }宏替换后程序内容如下:main ( ){int a=2, b=3;a*=10+20;b=b*10+20; /*初学者容易理解成b=b*(10+20); 从而得到错误的b值90*/ printf("a=%d,b=%d\n",a,b); }程序的运行结果为:a=60,b=50若想使b得到90的结果,可以将“#define NUM NUM1 + NUM2”改为“#define NUM (NUM1 + NUM2)”,即在“NUM1 + NUM2”外加一个(),从而在宏替换时,会将此括号原样展开出来。

【注意:程序中字符串常量即双引号中的字符与宏名相同时,不作为宏进行宏替换操作。

】例如,有程序:#define PRINT "Hello!"main(){printf("PRINT:%s\n",PRINT);} 宏替换后程序内容如下:main(){printf("PRINT:%s\n","Hello!");} 程序的运行结果是:PRINT: Hello!2.带参数的宏定义(1)格式:#define宏名标识符(参数列表)宏内容字符序列(2)说明:①参数列表由一个或多个参数构成,参数只有参数名,没有数据类型符,用逗号分隔②“宏内容字符序列”中通常会引用宏的参数(3)宏展开(即宏替换)首先将“宏内容字符序列”中的宏参数用实参替换,再将这个宏的实际内容文本替换掉源程序中的“宏名标识符(参数列表)”。

C语言程序设计第10章 编译预处理简明教程PPT课件

C语言程序设计第10章 编译预处理简明教程PPT课件

(2)定义一个宏名字之后,可以在其他宏定义中使用它。 如: #define ONE 1 #define TWO ONE+1 #define THREE ONE+TWO
计算机科学与技术学院—— C语言程序设计
10.2 #define
例10-1 宏定义及其使用 #define MESSAGE “You are right!\n”
计算机科学与技术学院—— C语言程序设计
第十章 编译预处理 内容提要
C预处理程序 #define
#include
条件编译指令
#undef
计算机科学与技术学院—— C语言程序设计
10.3 #include
10.3 #include
程序中的#include指令要求编译程序读入另一个源文件。被读入 文件的名字必须由双引号(”)或一对尖括号(<>)包围。如: #include”stdio.h” 或 #include<stdio.h> 都令编译程序读入并编译用于I/O函数处理的包含文件stdio.h。
计算机科学与技术学院—— C语言程序设计
10.3 #include
说明: (1)包含文件中还可以包含其它文件,称为嵌套包含(nested includes)。允许的最大嵌套深度随编译程序而变。 (2)用尖括号包围头文件时,搜索头文件时按编译程序的预先定 义进行,一般只搜索某些专门放置包含头文件的特殊目录。当头 文件用双引号包围时,搜索按编译程序实现时的规定进行,一般 指搜索当前目录,如未发现头文件,则再按尖括号包围时的办法 重新搜索。
10.2 #define
(4)#define指令还有一个重要功能:宏名字可以有变元。每当遇 到宏名字时,与之有关的变元都由程序中的实际变元替换。如上 例中的#define ABS(a) (a)<0?-(a):(a)。但要注意,#define ABS(a) (a)<0?-(a):(a)中变元a两边的括号是不能少的,否则, 会产生非预期结果。如: #define ABS(a) a<0?-a:a printf(”abs of (10-20):%d\n”,ABS(10-20)); ABS(10-20)替换为:10-20<0?-10-20:10-20,则输出结果为-30。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
z=POWER(x+y); 宏展开: z=x+y*x+y; 一般写成: #define POWER(x) ((x)*(x)) 宏展开: z=((x+y)*(x+y));
第 十 章
预 处 理 命 令
PI*r*r”
C
语 言 程 序 设 计 教 程 第 二 版
【例】用宏定义和函数实现同样的功能 #define MAX(x, y) (x)>(y)?(x):(y) ……. void main ( ) { int a, b, c, d, t; ……. t = MAX(a+b, c+d); …… } 宏展开:t = (a+b)>(c+d)?(a+b):(c+d); int max(int x,int y) { return(x > y ? x : y); } void main ( ) { int a, b, c, d, t; ……. t = max(a+b, c+d); ……… }
学习内容
预处理命令简介 宏定义 不带参数的宏定义 带参数的宏定义 文件包括 条件编译 本章小结
第 十 章
预 处 理 命 令
C
语 言 程 序 设 计 教 程 第 二 版
10.1
预处理命令简介
预处理命令:C源程序中以#开头、以换行符结尾的行 种类: 宏定义 #define、#undef 文件包含 #include 条件编译 #if、#ifdef、#else、#elif、#endif等 其他 #line、#error、#program等 格式: “#”开头 占单独书写行 语句尾不加分号
< >: 直接到系统指定的
第 十 章
A
预编译 处理后
预 处 理 命 令
A
源文件 prg1.cpp
B
源文件 prg2.cpp
B
新源文件 prg2.cpp
C
语 言 程 序 设 计 教 程 第 二 版
文件包含举例:
#include "head.h" #include "func.cpp" void main ( ) { int a , b, c; a = getnum ( ); b = getnum ( ); int max (int x, int y) c = max ( max(a, b), NUM ); { printf ("MAX = %d\n", c ); return (x > y ? x : y); } } #include <stdio.h> int #define (NUM 10 getnum ) 预编译 { int a; 处理后 scanf("%d", &a) return (a); }
预编译 处理后
a = 3.14; * 2 * 2;错误!Fra bibliotek第 十 章
预 处 理 命 令
{ N的内容是10 #define NUM2 20 { return (N * N); #define NUM (NUM1 + NUM2) int a = 2, b = 3; } void main ( ) a *= ( + 20) ; 10 { b = b * ( + 20) ; 10 int a = #define N 20 //第二次宏定义 2, b = 3; printf ("a = %d, b = %d\n", a, b); void a *= NUM; main ( ) } { N的内容是20 b = b * NUM; printf ("%d\n", N + f )); printf ("a = %d, b = %d\n", a, (b); 预编译 输出结果: } 处理后 } a = 60, b = 50 90
预 处 理 命 令
C
语 言 程 序 设 计 教 程 第 二 版
10.3
文件包含
功能 一个源文件可将另一个源文件的内容全部包含进来 一般形式
#define <包含文件名> 或 #define “包含文件名”
处理过程
“ ”:系统首先到当前目录 预编译时,用被包含文件的内容取代该预处理命令,再 “文件包含目录”去查 下查找被包含文件,如果 对“包含”后的文件作一个源文件编译 找被包含的文件 没找到,再到系统指定的 “文件包含目录”去查找。 #include "prg1.cpp"
第 十 章
预 处 理 命 令
本章主要讨论的 内容!
C
语 言 程 序 设 计 教 程 第 二 版
10.2
宏定义
可缺省,表示宏名 定义过或取消宏体
宏定义分为两种:不带参数的宏定义和带参数的宏定义。
1、不带参数的宏定义
一般形式
第 十 章
预 处 理 命 令
后面的单词串 容文本 #define SIZE 10 如 #define YES 1 #define INT_STR "%d" void main ( ) #define NO 0 void main ( ) { #define PI 3.1415926 { int a[10], i; 宏定义 #define OUT printf(“Hello,World”); int a[SIZE], i; for (i = 0; i < 10; i++) for (i = 0; i < SIZE; i++) scanf ("%d", &a[i]); scanf (INT_STR, &a[i]); 预编译 for (i = 10 - 1; i >= 0; i--) for (i = SIZE - 1; i >= 0; i--) 处理后 printf ("%d", a[i]); printf (INT_STR, a[i]); } }
第 十 章
预 处 理 命 令
C
语 言 程 序 设 计 教 程 第 二 版
带参的宏与函数区别
带参宏
处理时间 编译时 参数类型 无类型问题
函数
程序运行时 定义实参、形参类型
处理过程 不分配内存,简单的 字符置换
程序长度 变长
分配内存,先求实参值, 再代入形参
不变 调用和返回占时间
第 十 章
运行速度 不占运行时间
第 十 章
预 处 理 命 令
C
语 言 程 序 设 计 教 程 第 二 版
学习的意义
源程序生成执行文件的过程: 语 言 源 程 序 .c或.cpp C 目 标 程 序 .obj 执 行 程 序 .exe
编译
链接
预处理
第 十 章
预 处 理 命 令
#include <stdio.h> #define PI 3.14159 void main ( ) { float r = 4; printf (“s = %f\n”, PI*r*r); }
(stdio.h文件中的内容) #define NUM 10 int max (int x, int y) { return (x > y ? x : y); } int getnum ( ) { int a; scanf("%d", &a) return (a); } void main ( ) { int a , b, c; a = getnum ( ); b = getnum ( ); c = max ( max(a, b), NUM ); printf ("MAX = %d\n", c ); }
第 十 章
预 处 理 命 令
C
语 言 程 序 设 计 教 程 第 二 版
文件包含的优点:
一个大程序,通常分为多个模块,并由多个程序员分别 编程。有了文件包含处理功能,就可以将多个模块共用的数 据(如符号常量和数据结构)或函数,集中到一个单独的文 件中(如上例中的文件head.h和func.cpp)。这样,凡是要 使用其中数据或调用其中函数的程序员,只要使用文件包含 处理功能,将所需文件包含进来即可,不必再重复定义它们, 从而减少重复劳动。
#define 标识符 单词串 注意:宏替换时仅仅是将源程序中与宏名相同的 标识符替换成宏的内容文本,并不对宏的内容文本做 功能 任何处理。 宏名,被定义代表 宏体,是宏的内 指令名称 用指定标识符(宏名)代替字符序列(宏体)
C
语 言 程 序 设 计 教 程 第 二 版
宏定义注意事项
C程序员通常用大写字母来定义宏名,以便与变量名区别。 宏定义的位置任意,但一般放在函数外面。 如: #define PI 3.14159 宏定义时,如果单词串太长,需要写多行,可以在行尾 使用反斜线“\”续行符 例如:#define LONG_STRING "this is a very long string that is\ 宏名的作用域是从#define定义之后直到该宏定义所在 文件结束 example" used as an #define YES 1 #undef可终止宏名作用域
本章讨论之 重点!
预处理命令
C
语 言 程 序 设 计 教 程 第 二 版
学习目标
掌握#include、#define、#if、#ifdef、#else、#ifndef和 #endif等命令的用法; 掌握宏定义和宏替换的一般方法; 掌握包含文件的处理方法; 了解条件编译的作用和实现方法。
文件包含的几点说明
第 十 章
预 处 理 命 令
常用在文件头部的被包含文件,称为“标题文件”或“头 部文件”,常以.h(head)作为后缀,简称头文件。在头文 件中,除可包含宏定义外,还可包含外部变量定义、结构类 型定义等。 一条包含命令,只能指定一个被包含文件。如果要包含n 个文件,则要用n条包含命令。 文件包含可以嵌套,即被包含文件中又包含另一个文件。
相关文档
最新文档