函数和编译预处理.doc
C语言编译全过程

C语言编译全过程C语言是一种很常用的编程语言,而编译器则是将我们编写的C语言代码转换成可执行程序的工具。
本文将详细介绍C语言编译的全过程,包括预处理、编译、汇编和链接四个主要的阶段。
一、预处理预处理是编译过程的第一步,其主要作用是对源代码进行文本替换和宏展开。
在预处理阶段,编译器会根据以“#”开头的预处理指令,对代码进行一些预处理操作。
例如,我们可以使用“#include”指令将其他源文件包含进来,使用“#define”指令定义宏等。
预处理的结果是生成一个被替换掉所有宏和包含文件的新的代码文件。
这个新的代码文件将会被编译器进一步处理。
二、编译编译是将预处理后的代码转换成汇编代码的过程。
在编译阶段,编译器会对代码进行词法分析、语法分析和语义分析等操作,生成对应的中间代码。
中间代码是一种与机器无关的代码。
编译阶段是将C语言源代码转换为汇编语言的关键步骤。
汇编语言是一种相对于机器语言更易于阅读和编写的低级语言。
三、汇编汇编是将编译生成的中间代码转化为机器代码的过程。
在汇编阶段,编译器会将所有的汇编语句转换成机器指令,同时生成与机器硬件平台相关的目标文件。
目标文件是一种二进制文件,它包含了可执行程序的机器代码和其他相关信息。
目标文件中的机器代码是用来执行程序的指令。
四、链接链接是将多个目标文件和库文件合并为一个可执行程序的过程。
在链接阶段,链接器会将程序中使用的所有函数和变量的引用解析为实际的地址,同时处理符号表、重定位表等信息。
链接器还会将程序用到的库文件中的函数和变量与程序进行链接,以便程序能够正确地执行。
总结:C语言编译的全过程包括预处理、编译、汇编和链接四个主要阶段。
预处理将源代码进行宏替换和文件包含处理,编译将源代码转换为中间代码,汇编将中间代码转换为机器代码,而链接将多个目标文件和库文件合并为一个可执行程序。
理解C语言编译的过程对于了解C语言的底层工作原理以及程序执行的机制非常重要。
通过编译过程,我们可以将高级的C语言代码转换为底层的机器指令,使计算机能够直接执行我们编写的程序。
湖北理工学院c语言实验报告实验五[策划]
![湖北理工学院c语言实验报告实验五[策划]](https://img.taocdn.com/s3/m/f562119570fe910ef12d2af90242a8956becaa73.png)
实验五函数与编译预处理实验课程名:高级语言程序设计专业班级:软件工程学号:姓名:高敏实验时间:11.25-12.2 实验地点:K4-208 指导教师:刘天印(3)运行结果分析:用Workover和reset涵数转换i的值,并输出8.上机调试下面程序,观察静态局部变量在调用过程中的变化。
#include <stdio.h>void main( ){ int i ;int f(int);for ( i = 1; i <= 5; i ++)printf( "(%d):% d\n", i,f(i));printf(" \n");}int f ( int n){ static int j = 1;j = j * n;return( j );}解答:(1)源代码:#include <stdio.h>void main( ){ int i ;int f(int);for ( i = 1; i <= 5; i ++)printf( "(%d):% d\n", i,f(i));printf(" \n");}int f ( int n){ static int j = 1;j = j * n;return( j );}(2)运行结果:(3)运行结果分析: 输出1,2,3,4,5的阶层6. 编写程序,实现由主函数输入m 、n ,按下述公式计算并输出nm C 的值。
)!(!!n m n m C n m -=(1)源代码:#include<stdio.h> void main() {int i,m,n,N;int a=1,b=1,c=1;printf("please input m n:\n"); scanf("%d%d",&m,&n); for(i=1;i<m+1;i++) a*=i;for(i=1;i<n+1;i++) b*=i;for(i=1;i<m-n+1;i++){c*=i;} N=a/(b*c);printf("%d\n",N); }(2)运行结果:(3)运行结果分析)!(!!n m n m C n m -=说明:1.电子实验报告填写好后,以学生的学号+实验项目名作为该word文件名保存,例如某学生学号为20080001,姓名为某某,本次实验名称是:实验一顺序结构程序设计,则本次实验报告的保存文件名为:01某某实验一.doc。
函数与编译预处理

2021/5/8
5
局部变量
例1:void fun() { int a=3,b=4; printf("a=%d,b=%d\n",a,b); } main() { int a=1,b=2; fun(); printf("a=%d,b=%d\n",a,b); }
2021/5/8
结果: a=3,b=4 a=1,b=2
… }
2021/5/8
13
局部静态变量属于静态存储方式,它具有以下特点
局部静态变量在函数内定义,但它的生存期为整 个程序的运行期间。 局部静态变量的生存期虽然为整个程序,但其 作用域仍与自动变量相同,即只能在定义该变 量的函数内使用该变量。 对于局部自动变量来说,如果定义时不赋初值 则它的值是一个不确定的值。 局部静态变量定义时若不赋初值则自动赋0值 或空字符,而且是在编译时赋初值的,即只赋 初值一次,在程序运行时它已有初值。
第6章 函数与编译预处理
6.3 函数的递归调用 6.4 变量作用域与存储方式 6.5 编译预处理
2021/5/8
第10次课
1
教学目的: 1. 了解函数的递归调用形式及特点 2. 掌握程序中全局变量和局部变量的作用范围 3. 掌握变量的存储类别及生命用期 4. 了解简单宏定义的使用
重点: 1. 全局变量和局部变量的使用特点 2. 变量存储类别
8
3. 外部变量的使用
外部变量在定义位置到文件结束有效,但在明外部变量
int a;
main()
int fun(int x,int y) { extern int c;
int d; d=x*y*c;
{ extern int b; a=2;
printf("%d\n",fun(a,b)); }
第15章 C语言预处理和函数类型

同样#ifndef也可以与#else连用,构成的一般形式如下:
#ifndef 宏替换名 语句段1 #else 语句段2 #endif
其意义是:如果未定义#ifndef后面的宏替换名,则对“语句段1”进行编译,如果定 义#ifndef后面的宏替换名,则对语句段2进行编译。
条件编译
3.#undef命令 在前面讲#define命令时提到过#undef命令,使用#undef命令用来删除事先定义了的 宏定义。 #undef命令的一般形式如下: #undef 宏替换名
#include命令
在一个源文件中使用#include指令可以将另一个源文件的全部内容包含进来,也就是
将另外的文件包含到本文件之中。#include使编译程序将另一源文件嵌入带有#include的源
文件,被读入的源文件必须用双引号或尖括号括起来。例如: #include "stdio.h" #include <stdio.h> 这两行代码均使用C编译程序读入并编译,用于处理磁盘文件库的子程序。 上面给出了双引号和尖括号的形式,这里说下这两者之间的区别,用尖括号时,系统 到存放C库函数头文件所在的目录中寻找要包含的文件,这种称为标准方式;用双引号时, 系统先在用户当前目录中寻找要包含的文件,若找不到,再到存放C库函数头文件所在的目 录中寻找要包含的文件。通常情况下,如果为调用库函数用#include命令来包含相关的头文
掌握文件包含相关内容; 了解条件编译相关内容;
掌握内部函数相关内容;
掌握外部函数相关内容。
重点难点
重点:
宏定义的使用;
文件包含的使用; 内部函数和外部函数的使用
难点:
宏定义的方法;
教学内容
宏定义 ; #include命令 ; 条件编译; 内部函数和外部函数。
编译预处理

编译预处理1概述:编译预处理是在源程序正式编译前的处理。
预处理名令一般写在程序的最开头,并且以#开头的命令。
编译预处理命令不是c语言本身的组成部分,也不属于c语句,不能直接对他们编译。
在代码的正式编译之前(编译即指转换成二进制的机器语言),系统先对预处理命令进行处理,然后再由编译程序对处理后的程序进行正常的编译,得到可执行文件。
即对一个源程序进行编译时,系统会先引用预处理命令对源程序中的预处理部分进行处理,然后自动进行源程序的编译。
C语言提供3中预处理命令:宏替换文件包含条件编译他们均以#开头,并独占一个书写行,语句结尾不用;作为结束符。
2 宏替换(宏定义)分为两种:(1)无参数的宏替换是指用一个指定的标识符(即宏名)来代表程序中的一个字符串。
格式#define 宏名字符串如#define SIZE 10SIZE为宏名,此命令执行后,预处理程序对源程序中的所有SIZE的标识符用10替换。
说明:①宏名一般用大写字符,但不是必须的。
②字符串可以是常量,表达式,语句或多条语句可以是任何语句如输出语句,赋值语句等等③宏定义与变量定义不同,只是做字符的简单替换,不占内存空间,也不赋值④结尾不能加;,如果加了;,则;也作为字符串的一部分,一同参与替换。
⑤宏定义允许嵌套定义,即在宏定义的字符串中可以使用已经定义的宏名。
⑥宏定义要写在函数之外的,一般写在程序的开头,作用范围是从定义到本文件结束,出来这个文件失去作用了。
若要终止其作用,在需要终止前面加#undef 宏名⑦若宏名出现在双引号中,则将不会发生宏替换。
如printf(“ADD”) ADD是宏,这里不会进行宏替换了⑧替换文本不替换用户标识符中的成分宏名ADD不会替换标识符ADDIP中的ADD(2)有参数的宏替换宏定义中的参数为形式参数,在宏调用中的参数为实际参数。
格式:#define 宏名(形参)字符串各参数间用,隔开。
替换时,不仅要将宏展开,还要将形参替换为实参,但是仅仅是替换而不会去运算得出一个值,这点千万注意。
C语言 第4章 函数与编译预处理

4.2.4 对被调函数的声明和函数原型
变量要先定义后使用, 函数也如此。即被调函数的 定义要出现在主调函数的定 void swap(int x, int y) { …} main( ) {… swap(a,b); } main( ) {… c=max(a,b); } max(int x,int y) { …}
如下定义都是错误的 int max(x,y) { int x,y; …… } 或 int max(int x,y) { …… } 或 int max(x,y) int x,y,z; { z = x > y ? x : y; return( z ); }
√
花括号中也可以为空,这种函数叫空函数 。 不能在函数体内定义其他函数,即函数不能嵌套定义。
输出结果: 2.121320, 20.250000, 4.500000
9
⑷ 函数的种类
从函数定义形式分: ① 有参函数:
10
在主调函数和被调函数之间通过参数进行数据传
递, 如: int cube (int x) { … }
② 无参函数:
在调用无参函数时,主调函数不需要将数据传递
给无参函数。如:getchar( )
2014-10-10
【例4.2】无参函数的定义与调用。
void welcome ( ) { printf("*********************************\n"); printf(" Welcome to China \n"); printf("*********************************\n"); } main( ) { welcome( ); }
预编译处理

预编译处理【学习目标】◇理解编译预处理的概念。
◇了解宏定义的概念,掌握简单宏定义和带参数的宏定义的格式和使用方法。
◇了解文件包含的概念,掌握文件包含的格式和使用方法。
能在程序中合理使用#include预处理指令◇了解条件编译的概念,掌握条件编译的三种格式及其使用方法。
能在程序中合理使用#define, #if, #ifndef, #else, #undef, #elif等指令。
【重点和难点】重点:编译预处理的概念,简单的宏定义与文件包含指令的用法。
难点:带参宏定义,条件编译指令,会用条件指令解决文件的重复包含问题。
【学习方法指导】本章的内容比较简单,严格说来,它也不算是C++语言的组成部分。
但是,一般说来,任何程序都离不开预编译指令。
特别是文件包含指令和条件编译指令,应把它们搞清楚。
虽然可以用宏定义的方法定义常数,但推荐使用const语句定义常量。
在编程中,如果我们能恰当地运用条件编译,就可以提高程序运行的效率。
【知识点】宏定义;宏替换;简单的宏定义;带参数的宏定义;文件包含;条件编译第一节宏定义我们用C++进行编程的时候,可以在源程序中包括一些编译命令,以告诉编译器对源程序如何进行编译。
这些命令包括:宏定义、文件包含和条件编译,由于这些命令是在程序编译的时候被执行的,也就是说,在源程序编译以前,先处理这些编译命令,所以,我们也把它们称之为编译预处理,本章将对这方面的内容加以介绍。
实际上,编译预处理命令不能算是C++语言的一部分,但它扩展了C++程序设计的能力,合理地使用编译预处理功能,可以使得编写的程序便于阅读、修改、移植和调试。
预处理命令共同的语法规则如下:◇所有的预处理命令在程序中都是以"#"来引导如"#include "stdio.h""。
◇每一条预处理命令必须单独占用一行,如"#include "stdio.h" #include <stdlib.h>" 是不允许的。
C语言程序设计 第3版 第9章 编译预处理

#include "test2.c" static int sum(int n) {
int i,s=0; for(i=1;i<=n;i++)
s=s+fact(i); return s; }
static int fact(int n) {
C语言程序设计
第9章 编译预处理
第1讲:编译预处理基本形式
提纲
1.宏定义 2.文件包含 3.条件编译
1.宏定义
不带参数宏定义 带参数宏定义
格式:
#define 标识符 字符串
功能:
指定标识符代替一个较复杂的字符串。
注意说明:
(1)宏名一般习惯用大写字母,例如宏名PI。 (2)宏名用做代替一个字符串,不作语法检查。 (3)宏定义无需在末尾加“;” (4)宏定义的有效范围为#undef命令终止。 (5)在进行宏定义时,可以引用已定义的宏名。
char web[50]; int i=0; gets(web); while(web[i]!='\0') {
#if(R==1) if(web[i]>='A'&&web[i]<='Z') {web[i]=web[i]+32; i++;}
#else if(web[i]>='a'&&web[i]<='z') {web[i]=web[i]-32; i++;}
形式3:
#ifndef 标识符 程序段1
#else 程序段2
C语言文件的编译到执行的四个阶段

C语言文件的编译到执行的四个阶段C语言程序的编译到执行过程可以分为四个主要阶段:预处理、编译、汇编和链接。
1.预处理:在这个阶段,编译器会执行预处理指令,将源代码中的宏定义、条件编译和包含其他文件等操作进行处理。
预处理器会根据源代码中的宏定义替换相应的标识符,并去除注释。
预处理器还会将包含的其他文件插入到主文件中,并递归处理这些文件。
处理后的代码被称为预处理后的代码。
2.编译:在这个阶段,编译器将预处理后的代码转换成汇编代码。
汇编代码是一种低级的代码,使用符号来表示机器指令。
编译器会对源代码进行词法分析、语法分析和语义分析,生成相应的中间代码。
中间代码是一种与特定硬件无关的代码表示形式,便于后续阶段的处理。
3.汇编:在这个阶段,汇编器将中间代码转化为机器可以执行的指令。
汇编器会将汇编代码翻译成二进制形式的机器指令,并生成一个目标文件。
目标文件包含了机器指令的二进制表示以及相关的符号信息。
4.链接:在C语言中,程序通常由多个源文件组成,每个源文件都经过了预处理、编译和汇编阶段得到目标文件。
链接器的作用就是将这些目标文件合并成一个可执行文件。
链接器会解析目标文件中的符号引用,找到其对应的定义并进行连接。
链接器还会处理库文件,将使用到的函数和变量的定义从库文件中提取出来并添加到目标文件中。
最终,链接器生成一个可以直接执行的可执行文件。
以上是C语言程序从编译到执行的四个阶段。
每个阶段都有特定的任务,并负责不同层次的代码转换和处理。
通过这四个阶段,C语言程序可以从源代码转换为机器能够执行的指令,并最终被计算机执行。
编译预处理的名词解释

编译预处理的名词解释编译预处理(Compiler preprocessor)是计算机科学中一个重要概念,它是编译器的前处理步骤,用于在源代码被编译前对其进行一系列的转换和操作。
编译预处理器是编译过程中的一个组件,它处理源代码中的预处理指令,对代码进行一些宏展开、条件编译等操作,然后再将处理后的代码提交给编译器进行编译。
一、编译预处理的定义和作用编译预处理是指在编译过程中对源代码进行处理的一系列操作。
预处理器会通过扫描源代码中的特殊指令,执行相应的操作,并将结果替换回源代码中。
预处理器可以实现代码的复用、条件编译、宏定义等功能,大大提高了代码的灵活性和可维护性。
编译预处理器最常用的功能之一是宏展开(Macro expansion)。
宏是一段预定义的代码片段,在代码中使用宏可以简化重复的代码,提高代码的可读性和维护性。
预处理器会将所有使用宏的地方替换为宏的定义内容,以此实现代码的复用。
二、条件编译条件编译(Conditional Compilation)是编译预处理中的一项重要功能。
通过条件编译,我们可以根据不同的条件选择性地编译源代码中的一部分。
这对于不同平台、不同版本的代码兼容性是非常有用的。
条件编译使用预处理指令#if、#ifdef、#ifndef、#elif、#else和#endif来实现。
我们可以根据条件表达式的结果来选择编译不同的代码块,从而实现特定条件下的代码执行。
三、头文件包含头文件包含(Header File Inclusion)是编译预处理中的另一个重要功能。
头文件包含用于将一个源文件中的代码引入到另一个源文件中。
这样,我们可以在不同的源文件中共享函数、常量、宏等定义,提高代码的复用性。
头文件被放置在使用它的源文件中,通常使用#include指令来进行包含。
头文件包含具有层次结构,可以通过嵌套的方式来引入多个头文件。
四、预定义宏预定义宏(Predefined Macros)是编译预处理器提供的一些内置宏,在编译过程中可供我们使用。
C语言对源程序处理的四个步骤:预处理、编译、汇编、链接——预处理篇

C语⾔对源程序处理的四个步骤:预处理、编译、汇编、链接——预处理篇预处理1)预处理的基本概念C语⾔对源程序处理的四个步骤:预处理、编译、汇编、链接。
预处理是在程序源代码被编译之前,由预处理器(Preprocessor)对程序源代码进⾏的处理。
这个过程并不对程序的源代码语法进⾏解析,但它会把源代码分割或处理成为特定的符号为下⼀步的编译做准备⼯作。
2)预编译命令C编译器提供的预处理功能主要有以下四种:1)⽂件包含 #include2)宏定义 #define3)条件编译 #if #endif ..4)⼀些特殊作⽤的预定义宏a、⽂件包含处理1)⽂件包含处理⽂件包含处理”是指⼀个源⽂件可以将另外⼀个⽂件的全部内容包含进来。
C语⾔提供了#include命令⽤来实现“⽂件包含”的操作。
2)#include< > 与 #include ""的区别" "表⽰系统先在file1.c所在的当前⽬录找file1.h,如果找不到,再按系统指定的⽬录检索。
< >表⽰系统直接按系统指定的⽬录检索。
注意:1. #include <>常⽤于包含库函数的头⽂件2. #include " "常⽤于包含⾃定义的头⽂件 (⾃定义的头⽂件常⽤“ ”,因为使⽤< >时需要在系统⽬录检索中加⼊⾃定义头⽂件的绝对地址/相对地址否则⽆法检索到该⾃定义的头⽂件,编译时会报错)3. 理论上#include可以包含任意格式的⽂件(.c .h等) ,但我们⼀般⽤于头⽂件的包含。
b、宏定义1)基本概念在源程序中,允许⼀个标识符(宏名)来表⽰⼀个语⾔符号字符串⽤指定的符号代替指定的信息。
在C语⾔中,“宏”分为:⽆参数的宏和有参数的宏。
2)⽆参数的宏定义#define 宏名 字符串例: #define PI 3.141926在编译预处理时,将程序中在该语句以后出现的所有的PI都⽤3.1415926代替。
C语言 函数 预处理

例6-1 文件包含预处理语句的使用
mymath.h的内容如下: # define ADD(x,y) (x+y) # define MUL(x,y) ((x)*(y)) # define PI 3.1415926 # define G 2.718 test.c内容如下: # include “mymath.h” main ( ) { int a=6,b=9; printf(“a+b=%d\n”,ADD(a,b)); printf(“a*b=%d\n”,MUL(a,b)); }
(5)使用宏次数多时,宏展开后源程序长,因为每 展开一次都使程序增长;而函数调用不使程序变长。 (6)宏替换不占用运行时间,而函数调用则占用运 6 行时间(分配内存单元、保护现场、值传递、执行 函数、返回函数值等)。
6.3 条件编译 .
在很多情况下,为了增强程序的可移植 性,C语言源程序中包含了各种版本的程序段, 但在某种情况下,只希望对一部分内容进行 编译,即为其指定编译的条件,此时称为条 件编译。
例6-3 带参数的宏定义 #define POWER(x) ((x)*(x)) main() { int y; scanf(“%d”,&y); printf(“y=%d, y*y=%d\n”,y, POWER(y)); }
从上述例题中可以看出,带参数的宏定义与函 数的使用非常相似,但二者是不同的。两者的区别 有如下几点: (1)函数调用时先求出实参的值,然后代入形参。 而带参数的宏定义只是进行简单的字符替换。 (2)函数调用是在程序运行时处理的,并分配临时 的内存单元。而宏展开则是在编译预处理时进行的, 在展开时并不分配内存单元,不进行值的传递,也 没有“返回值”。
第6章 编译预处理 章
程序编译的四个步骤

程序编译的四个步骤程序的编译过程通常分为四个步骤:预处理、编译、汇编和链接。
第一步:预处理(Preprocessing)预处理是编译过程的第一个步骤。
在这一步骤中,预处理器将对源代码进行处理,以便于后续的编译。
预处理器通常会执行以下任务:1.去除注释:将源代码中的注释(单行、多行注释)删除,以便于后续的处理。
2.展开宏定义:替换源代码中的宏定义,在源代码中使用宏定义的地方,将其替换为宏定义的内容。
3.处理条件编译指令:根据条件编译指令的条件,决定哪些代码需要编译,哪些代码需要忽略。
4.处理头文件包含指令:将头文件包含指令替换为头文件的内容,以确保源代码中可以使用头文件中定义的函数、变量等。
编译是预处理之后的一步,编译器将对预处理后的文件进行处理。
编译器通常会执行以下任务:1. 词法分析(Lexical Analysis):将源代码分解成一个个的词素,如关键字、标识符、运算符等,并生成相应的记号。
2. 语法分析(Syntax Analysis):根据词法分析生成的记号,将其按照一定的文法规则进行组织,构建抽象语法树。
3. 语义分析(Semantic Analysis):对抽象语法树进行分析,检查程序是否存在语义错误,如类型不匹配、未定义的变量等。
4. 代码生成(Code Generation):根据语义分析的结果,将抽象语法树转化为目标机器的汇编代码。
第三步:汇编(Assembly)汇编是编译过程的第三步,将编译器生成的汇编代码转化为机器码。
汇编器(Assembler)会执行以下任务:1.识别指令和操作数:根据汇编代码的语法规则,识别出每个指令以及对应的操作数。
2.生成机器码:将汇编指令和操作数翻译成机器码表示形式。
3.符号解析:解析并处理所有的符号引用,如函数、变量等的引用。
第四步:链接(Linking)链接是编译过程的最后一步,将编译器生成的目标代码和其他库文件进行合并。
1.解析外部符号引用:将目标代码中引用的外部符号(函数、变量等)与其他目标代码或库文件中的定义进行匹配。
C语言课件—编译预处理

#include <stdio.h> #define sqr(x) ((x)*(x))
#include "powers.h" #define cube(x) ((x)*(x)*(x))
void main() { int n调;试方法
#define quad(x) ((x)*(x)*(x)*(x))
print1f.("n编u辑mpboerw\teersx.ph2,保\t e存xp3\t exp4\n");
❖宏体及各形参外一般应加括号()
例 #define POWER(x) x*x
x=4; y=6;
z=POWER(x+y); 宏展开:z=x+y*x+y; 一般写成: #define POWER(x) 宏展开: z=((x+y)*(x+y));
((x)*(x))
Macro Definition
例. 带参数的宏与函数实现同样功能
第七章 编译预处理
概述 宏定义 文件包含 条件编译
Next chapter
Introduction
作用:编译程序的一部分,将特殊命令扩展到程 序中,生成扩展C源程序
种类
❖宏定义 #define ❖文件包含 #include ❖条件编译 #if--#else--#endif
格式:
❖“#”开头 ❖占单独书写行 ❖语句尾不加分号; ❖定义位置任意,决定其作用域
print2f.("-将---p\to-w---e\tr-s--.h--文\t-件---存--\n放"到); 某一目录下
for(n3=. 1;编n<辑=fMmAaXin;.nc,++将) powers.h包含进来
《C语言程序设计(第五版)》-第8章编译预处理

此程序段将显示SIZE,而不是1000。
C语言程序设计
第8章 编译预处理
8.1.1 不带参数的宏定义
说明:
(5)可以引用前面已经定义的宏名来定义新的宏,示例代码如 下: #define I1 30 #define I2 60 #define J I1+I2 #define K J*2+J/2+I2
其含义是用指定的宏名(即标识符)来代表其后的字符串。
C语言程序设计
第8章 编译预处理
8.1.1 不带参数的宏定义
示例代码如下: #define SIZE 1000 #define PI 3.1415926 #define FORMAT "%d,%d,%d\n"
用标识符SIZE来代替字符串1000, 用标识符PI来代替字符串3.1415926, 用标识符FORMAT来代替字符串"%d,%d,%d\n", 在编译预处理时,将程序中在该命令以后出现的所有的SIZE用1000
本章教学重点:宏定义的两种形式,文件 包含的使用方法。
本章教学难点:带参数的宏定义。
C语言程序设计
第8章 编译预处理
主要内容:
8.1 宏定义 8.2 “文件包含”处理 8.3 条件编译
C语言程序设计
第8章 编译预处理
第8章 编译预处理
编译预处理是指一些行首以#开头的特殊语句。 在对程序进行通常的编译之前,必须先对程序中这 些特殊的命令进行“预处理”,即根据预处理命令, 对程序作相应的处理。
第8章 编译预处理
本章概述 本章的学习目标 主要内容
C++程序设计(谭浩强完整版)

在一个函数中调用另一函数(即被调用函数)需要 具备哪些条件呢? 1) 被调用的函数必须是已存在的函数
2) 如果使用库函数,必须用 #include < math.h> 3) 函数调用遵循先定义、后调用的原则,即被调 函数应出现在主调函数之前。
21
float max(float x, float y) { float z;
实际参数
形参列表说明
cout<<“The max is”<< c<<endl;
}
10
函数参数和函数的值 形参是被调函数中的变量;实参是主调函数 赋给被调函数的特定值。实参可以是常量、 变量或复杂的表达式,不管是哪种情况,在 调用时实参必须是一个确定的值。 形参与实参类型相同,一一对应。 形参必须要定义类型,因为在定义被调函数 时,不知道具体要操作什么数,而定义的是 要操作什么类型的数。
i
x 5
j 7 6
{ int i=2, x=5, j=7; void fun(int,int); 2 fun ( j, 6); cout<<i<<„\t‟<< j<<„\t‟<< x<<endl; } void fun ( int i, int j) { int x=7; cout<<i<<„\t‟<< j<<„\t‟<<x<<endl;
先计算,后 赋值
cout<<“The max is”<<c<<endl;
12
说明:
1、在未出现函数调用时,形参并不占内存的存储单元,只 有在函数开始调用时,形参才被分配内存单元。调用结束 后,形参所占用的内存单元被释放。 2、实参对形参变量的传递是“值传递”,即单向传递。在 内存中实参、形参分占不同的单元。 3、形参只作用于被调函数,可以在别的函数中使用相同的 变量名。 a 5 8 x y 5 形参 b 8
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
函数和编译预处理函数和编译预处理(第五章)一、单项选择题1.关于函数,以下正确的描述是(B)A,函数的定义可以嵌套,但函数的调用不可以嵌套B,函数的定义不可以嵌套,但函数的调用可以嵌套C,函数的定义可以嵌套,函数的调用也可以嵌套D,函数的定义和函数的调用都不M以嵌套2.关键字inline用于定义内联函数,定义时,是将该关键字(D )A.取代定义函数的类型标识符B.取代被定义的函数名C.加在类型标识符之后D.加在类型标识符之前3.以下不正确的描述为(B )A.在函数之外定义的变量称为外部变量,外部变量是全局变量。
B.在函数之内说明的外部变量是局部变量,仅在本函数中有效。
C.在函数之外说明的静态变量也是全局变量,其作用域是文件作用域。
D.文件作用的域范围是一个程序文件,但必须符合“定义在前,使用在后”的规则。
4.以下正确的描述为(C )A,每个C++程序必须在开头用预处理命令^include <iostream. h>B,预处理命令必须位于C++源程序的首部C.在C++中,预处理命令都以#开头D.C++语言的预处理命令只能实现宏定义和条件编译的功能5.在下面的函数原型说明中,存在着语法错误的是(D )A.void BC(int a, int) ;B. void BD(int , int);C. void BE(int , int=5) ;D. int BF(int x ; int y);6.下列哪个不是重载函数在调用时选择的依据(C )A.形参类型B.形参个数C.函数返回值类型D.函数名7.在一个源程序文件中有以下函数定义,其中(D )是重载函数。
A.ABCB. BCDC. ACDD.全部A) int sum (float x, int y) B) float sum (float x, int y, char z) (. . . )C) float sum (float x, float y) D) int sum(int x, int y, char z) (. . . )8.有一个函数原型abc(float x, float y);该函数的返回值类型为(C )A.voidB. doubleC. intD. float9.在程序中,函数声明语句正确位置是(D )A.随便任何位置B.不包含在另一函数中的任何位置。
C.该函数使用前的任何位置D.该函数使用前的任何位置,但不包含在另-一函数中10.C++构造内联函数的思想是(A )A.用空间换时间B.用时间换空间C.用形参换实参D.用实参换形参11.在以下存储类型中,(D)是用于定义动态类型的变量。
A. static 和autoB. register 和externC. register 和staticD. auto 和register12.下列各类变量,哪个不是局部变量(B )A. register型变量B.外部static变量C. auto型变量D.函数形参13.以下关于调用函数时,形、实参结合的通用规则不正确的描述为(B )A.实参可以是变量,也可以是常数或者表达式。
B.实参的个数可以多于形参,也可以少于形参。
C.系统将为形参分配内存单元。
D.实参必须与对应的形参类型相兼容。
M.假设有宏定义:^define NUM 15^define DNUM NUM+NUM则表达式DNUM/2+NUM*2的值为(C )A. 45B. 67C. 52D. 9015.对于一个功能不太复杂,并且要求加快执行速度,选用(A )合适。
A.内联函数B.重载函数C.递归调用D.嵌套调用16.若有以下函数调用语句:fun ((a+b, (x, y)), fun (n+k, d), (a, b));其中实参的个数是(A )A. 3B. 4C. 5D. 617.以下叙述下不正确的是(D )A.在函数中,通过return返[^函数值。
B.函数中可以有多条return语句。
C.主函数main ()也可以带有形参。
D.调用函数,必须在一条独立的语句中完成。
18.设有函数定义:int fl (void) (return 100,200;},调用函数fl ()时,(C )A.函数返回值为100B.函数返回二个值100和200C.函数返回值为200D.语句"return 100,200;”语法错,不能调用函数19.调用宏定义和语句:ftdefine M(a, b) a*b; //Eint x=M(3+4, 5+6), y; //Fy=M(3, 4); //G则(B )A.编译时,E行有语法错B.编译时,F行有语法错C.编译时,G行有语法错D.编译时,F行和G行有语法错20.在一个源文件中定义的全局变量的作用域为(D )A.本文件的全部范围B.本程序的全部范围C.本函数的全部范围D,从定义该变量的位置开始至本文件的结束21.对于下面几个函数,(C )是重载函数。
void f(int x) ( ... ) //Iint f(int y) {.・. ) //2int f (int i , int j ) ( ... } //3float k(int x ) ( ... } //4A. 4 个全部 B. 1 和 4 C. 2 和 3 D. 3和422.编译系统根据同一个程序中(A )识别重载函数。
A.形、实参的个数和类型的差别C.形、实参个数,类型和返回值类型的差别23.以下正确的说法是(D )A.用户若需要调用标准库函数,调用前必须重新定义B.用户可以直接调用所有标准库函数C.用户可以定义和标准库函数重名的函数,但是在使用时调用的是系统库函数D.用户可以通过文件包含命令将系统库函数包含到用户源文件中,然后调用系统库函数24.以下叙述中不正确的是(D )A.在不同的函数中可以使用相同名字的变量B.函数中的形式参数是局部变量C.在一个函数内定义的变量只在本函数范围内有效D.在一个函数内的复合语句中定义的变量在本函数范围内有效二、填空题1.当在块作用域内的局部变量与全局变量同名时,则2.在类型前加关键字3.有如下宏定义^define X(a) (a)*a,则表达式X(4+5)的值为4.变量分为全局和局部两种,0。
5.内联函数的实质是在编译时把函数的函数体直接插入到函数调用处o6.C++7.在函数的递归调用时,若在A函数内调用B函数,而在B函数内调用A函数,称为8.若myheadfile.h为用户自定义的头文件,则在程序开始处包含此头文件的格式为#include" myheadf ile. h” 。
9.具有块作用域的变量都是变量.10.递归函数在执行过程中,存在二个过程是11.有如下宏定义Sdefine X(a) a*a,则表达式X(4+5)的值为12.在for13.静态整数变量有确定的初值,其缺省的初值为0。
14.在设计递归方法程序时,为防止进入无穷递归,在递归程序中一定要有递归结束条件。
15.若在程序前定义了#define ring(x, y, z) x*y/z ,且在程序中有语句s=ring(25, 6, 1. 5);则程序运行时执行的相应语句(宏扩展)为s二25*6/1. 5。
16.在一个函数定义的函数体中又出现直接或间接地调用该函数本身称为函数的17.若要定义只能用于本文件的内部函数时,则在函数的类型标识符前加修饰词。
18.函数原型为abc(float x, char y);该函数的返回值类型为int。
19.在C++程序中,当函数调用在前、函数定义在后时,则应在主调函数中,在调用前增加对被调函数的原型说明。
20.在函数的递归调用时,若在A函数内调用A函数,称为21.若有宏定义:#defin X 2#defin Y(n) ((X+l)*n)则执行语句:z=2*(X+Y(X+2));后,z的值是20 o三、阅读程序题1.^include <iostream.h>void test (int x, int y=20)cout«" x=";y="<<y<<endl;void main()int x=10;int y=15;test (x, y);test (x);}执行以上程序后,输出的笫一行结果:x=10;y=15第二行结果:x=10;y=202.#include<iostream. h>#define ABCvoid main。
(float s, x, y, z;S=l;y=z=0;whi]e (s<=10)Icin>>x;y+=x ;s++;z=y/10;#ifdef ABCcout« y«endl;#endifcout<<z<<endl;}问题1:程序中二个输出语句分别输出什么信息。
问题2:取消或保留语句^define ABC,对程序输出有何影响?(1)y输出10个实数之和z输出10个实数的平均值(2)取消语句ftdefine ABC,则程序输出为10个实数的平均值。
保留语句define ABC,则程序输出为10个实数之和及10个实数的平均值。
3.# include <iostream. h># define AREA (a, b) a*b# define PREIMETER(a, b) 2*(a+b)void main(void)( cout«z/Area=z/«AREA (1+2, 3+4) «endl;cout«'Preimete=,z«PRETMETER(5, 6)«endl; }以上程序段执行后,输出是:Area=11Preimete=224.^include <iostream.h>int i=2, j=3;int f (int a, int b)( int c=0; static int d=3;d++;if(a>b) c=l;else if (a==b) c=0;else c=-l;i=j+l;return (c+d);}void main(){ int p;P=f(i, j);cout«i«,«j«f , ,«p«endl;i=i+l; P=f(i, j);cout«i«,,' «p«endl; i=i+l; p=f (i, j);cout«i«,«j«y«p«endl;!执行以上程序后,第一行输出:4,3,3第二行输出:4,3,6第三行输出:4,3,75.# include <iostream. h>int a=5;void main() (int a=10, b=20;cout «a«J \t,<<b«end l; { int a=0, b=0;for (int i=l; i<6; i++) (a+=i; b+=a;}cout <<a<<J\t' <<b<<*\t' <<::a<<endl; cout <<a<<J\V <<b<<endl;)执行以上程序后,第一行输出:10, 20第二行输出:15, 35,5第三行输出:10, 206.^include <iostream. h>void fun ();void main()(int i;for (i=0;i<5;i++)fun ();;void fun()(static int m=0;cout<<++m;;执行以上程序时,输出结果是:12345 7.#include <iostream. h>void main(void){ int i;void addl(void);void adc!2(void);for (i=0;i<3;i++){ addl ();add2 ();cout<<endl;}}void addl(vold)( int x=0;x++;cout<<x<<,\t';void add2(vold)( static int x=0;x++;cout<<x<<,\t';执行以上程序时,输出结果是:1112 138.#include <iostream. h> int fac ()int b=0;static int c=3;b++; c++;return b+c;}void main( ) (for(int j=0; j<3; j++) cout<<fac()<<, \t';执行如上程序后,输出结果是:5 6 79.#include <iostream. h>int fun (double a, double b);void main()(cout<<fun (2.5,3.5)<<endl;;int fun(double a,double b)(return a*b;执行以上程序时,输出结果是:810.#include<iostream.h>void fun(int n) (cout«n%10;if(n<10) return;else fun(n/10);}void main() {int n;cin>>n;fun(n);cout<<endl;}执行以上程序时输入:469257,输出结果是:752964 11.^include <iostream. h>void change(int x, int y)(x+=10;y+=10;cout<<" x="<<x<<,? ;y=v <<y<<endl;!void main()(int x=10;int y=15;coutXV" x="«x«,?;y=ff<<y«endl; change (x, y);cout«" x=" «x«" ;y=" «y«endl;}上面的程序编译并运行,程序的输出结果有三行,请写出程序运行的第一行结果:x=10;y=15第二行结果:x=20;y=25第三行结果:x=10;y=1512. #include<iostream. h> int f (int x)( static int u=l;x+=x;return u*二x;!void main(vold)( int x=10;cout<<f(x)<<*\n ; cout<<f(x)<<*\n J ; }程序输出的第一行是:20程序输出的第二行是:40013. #include <iostream. h>#define M 20#define N 10^define L(r) r*rvoid main()}以上程序段执行后,输出是40012014. ^include <iostream. h>int i=l;int fac(int n)( static int f=l;f=f*n;return (f);!void main()( int i, p=0;for(i=l;i<=3;i++)p二fac(i); cout<<p<<endl; P二0;for (i=l; i<=3; i++) p=p+:: i++; cout«p«,,J ; P=1 ;for(i=l;i<=3;i++)p=p*―::i; cout<<p<<endl; ;程序输出的第一行是:6程序输出的第二行是:6, 6程序中的::i是指:全局变量il5. //文件名:cppfile_l. cppint x=l, y=2;static int z=3;extern void add (void);void main(){ addO ;cout«"x二”«x«‘\t'=〃«y <<* \t J <<,,z=,,<<z<<endl; } //文件名:cppfile_2. epp#include <iostream. h>extern int x,y;void add (void)( x+=3;y+=4;cout<<,,x=/z«x<<,\t' <<,,y=z,«y«endl;!执行以上程序时,输出结果是:x=4 y二6x=4 y=6 z=316. ^include <iostream. h>int f (int a, int b)( if(a>b)return b+a; else b*f(++a,―b);return a*f(a, b);如果主函数中有语句cout«f(l,3)«'\n';输出是:24 如果主函数中有语句cout«f(3, 1)« \n ;输出是:417. ^include <iostream. h>int i=2,j=3;int f (int a, int b){ int c=0; static int d=3;d++;if(a>b) c=l;else if (a==b) c=0;else c=-l;i=j+l;return (c+d);!void main()( int p;P=f (i, j);cout«i«,«j«y«p«endl;i=i+l; p=f(i,j);cout«i«,«j«, , y«p«endl; i=i+l; p=f (i, j);cout«i«,«j«y«p«endl;;执行该程序的第一行输出是:4, 3,3第二行输出是:4, 3,6第三行输出是:4,3,7fun3 (int x) (static int a=3;a=x;return (a);)void main() (int k=2, m=l, n;n=fun3(k) ; n=fun3(m+n) ; cout«n«endl; )程序输出是:319.#include <iostream. h>int i=2, j=3;int f (int a, int b)( int c=0, d二3;d++;if(a>b) c=l;else if (a==b) c=0;else c=T;i=j+l;return (c+d);}void main() { int p;P=f(i, J);cout«i«,<<j«?«p«endl;i=i+l; p=f(i,j); cout«i«,<<j«?«p«endl;i=i+l; p=f(i,j); cout«i«,«j«f«p«endl;}执行该程序的第一行输出是:4,3,3第二行输出是:4,3,5第三行输出是:4,3,520.若有宏定义如下:ftdefine X 5^define Y X+l#define Z Y*X+2则执行以下语句后,int a; a=Y;cout<<Z;cout<<一a<<endl;输出结果是:12521.#include <iostrearn. h>int fac(int n)( int z;if (n>0)z=n*fac(n-2);elsez= 1 ;return z;}void main(void){ int x=7, y;y二fac (x);cout<<y<<endl;}执行以上程序时,输出结果是:105 22.#include <iostream. h>void fun();int n=5;void main ()(int n=10;cout<<++n<<endl;fun ();;void fun()(cout<<n++<<endl;执行以上程序时,输出结果是:11 523.# include <iostream. h>switch(ch) {case ' A' : case ' a,:cout !/z; break; case ' B' : case ' b':cout <<〃good!〃;break; case ' C' : case ' c':cout <<〃pass!〃;break; default:cout <<〃bad!〃;break; }}void main() (char al=,b', a2- C', a3=' f' ; SB (al) ; SB (a2) ; SB (a3); SB (' A') ; cout <<endl; }执行以上程序时,输出结果是:good! pass! bad! wel 1!24.设有宏定义如下:#def ine MTN (x, y) (x) > (y) ? (x) : (y)#define T (x,y,r) x*r*y/4则执行以下语句后,int a=l, b=3, c=5, si, s2;sl=MIN(a=b, b~a);s2=T(a++, a*++b, a+b+c);si的值为:3s2的值为:2725.#include <iostrearn. h>int add(int x, int y=8);int a=4;cout«add (a) <<endl:cout<<add(a, add (a))<<endl;}int add(int x, int y)(return x+y;}执行以上程序时,输出结果是:12 1626.#include <iostream. h>fun (int x)( static int a=3; a=x; return(a); }void mai n ()( int k=2, m=l,n; n=fun(k); n=fun (m+n); cout<<n<<endl; 执行以上程序时,输出结果是:3四、完善程序题1.此程序为打印如下图形,请将程序补充完整。