第9章 预处理命令

合集下载

C语言 第九章 预处理命令

C语言 第九章 预处理命令
第九章 预处理命令
目的: 简化程序的编写 ; 提高程序的模块化、可读性、可移植性。
有三种类型的预处理命令: 1. 宏定义命令; 2. 文件包含命令; 3. 条件编译命令。
为了与C语句区别,这些命令均以“ # ”开头。
处理流程: 第一次编译扫描时,将预编译命令处理完, 然后再进行正式编译,生成目标代码。
#define f(a)
(a)* b
若有:f(x+y) 则应有:
(x+y)b
若有:f(x+y+z) 则应有:
预编译后, z = f(x+y) 变成: z = x+y*b 结果为: z=31
(x+y+z)b
(这个结果与初始设想不一致)
“带参数宏定义” 必须注意以下几个方面: 1. 宏定义时要考虑实参(替换)的各种可能, 防止出 现二义性。
3. #include后的文件名既可用“ ”,也可用< >, 二者区别:
“ ”首先在当前目录中找,然后再去标准目录中找。
< > 只在标准目录(include目录)中找。
为提高预处理的搜索效率,通常对自定义的 非标准头文件使用方式一;而对系统提供的标准 头文件(如:math.h、stdio.h等)使用方式二。
将返回值 6 将返回值 8
但二者还是有区别的:
1) 宏替换在预编译时进行;
而函数调用在程序运行时进行
2) 宏展开时,仅仅是将宏体中的形参简单 地置换为实参,不计算实参值,也不会带来任何 返回值; 而函数调用要进行: l 计算实参值(假定用 2+3、 9–1作为实参将 被计算出来)、 l参数传递(将 5、8 传给形参x、y)、
这些文件要用到公用信息时,只要在文件 中加入#include “f.h”这么一行命令既可。这样 就不必在f1.c、…… 、fn.c每个文件中都去重 复定义这些公用的信息。

第九章预处理命令(5503)

第九章预处理命令(5503)

1.下面叙述中正确的是(A )。

A.带参数的宏定义中参数是没有类型的B.宏展开将占用程序的运行时间C.宏定义命令是C语言中的一种特殊语句D.使用#include命令包含的头文件必须以“.h”为后缀2.在宏定义#define PI3.14159中,用宏名代替一个( D )A.常量B.单精度数C.双精度数D.字符串3.下面有关宏替换的叙述不正确的是( D )A.宏替换不占用运行时间B.宏名无类型C.宏替换只是字符替换D.宏名必须用大写字母表示4.C语言的编译系统对宏命令的处理是( D )A.在程序运行时进行的B.和C程序中的其他语句同时进行编译的C.在程序连接时进行的D.在对源程序中其它成分正式编译之前进行的5.下列定义不正确的是(C )。

A.#define PI 3.141592B.#define S345C.int max(x,y); int x,y; { }D.static char c6.有如下宏定义 #define s(a) a*3 ,则执行表达式x=s(1+2)后,变量x的值为( D)。

A.10B.9C.8D.77.以下说法中正确的是( D)。

A.#define是C语句B.#define是库函数C.#define是自定义函数D.#define是预处理命令8.在“文件包含”预处理语句的使用形式中,当#include后面的文件用了“”(双引号)时,寻找被包含文件的方式是(B)。

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

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

预处理指令详解

预处理指令详解

#pragma#pragma 预处理指令详解在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。

#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。

依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

其格式一般为: #Pragma Para其中Para 为参数,下面来看一些常用的参数。

(1)message 参数。

Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。

其使用方法为:#Pragma message(“消息文本”)当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。

假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法#ifdef _X86#Pragma message(“_X86 macro activated!”)#endif当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_X86 macro activated!”。

我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。

(2)另一个使用得比较多的pragma参数是code_seg。

格式如:#pragma code_seg( ["section-name"[,"section-class"] ] )它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

(3)#pragma once (比较常用)只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。

C语言程序设计教程CJ_04预处理命令_潭浩强第3版

C语言程序设计教程CJ_04预处理命令_潭浩强第3版

Page 6
辽宁师范大学
蔡静
带参宏替换 函数调用 编译时替换, 运行时调用, 编译时替换 不占用内存 运行时调用 占用内存 只替换不计算 计算 替换使程序代码加长 不加长 存在数据类型问题 不存在数据类型问题
Page 7
辽宁师范大学
蔡静
9.2 “文件包含 处理 文件包含”处理 文件包含
通过预处理命令#include把另一个文件的全部内容包含到本 文件中。 格式1: #include <文件名 文件名> 文件名 只按系统指定的标准方式(从编译系统所在子目录中)检索 文件目录。 格式 2: #include “文件名” 文件名” 文件名 系统首先在当前源文件所在目录中寻找该文件,若找不到, 再按系统指定的标准方式检索其他文件目录。 例:9.6
Page 9
辽宁师范大学
蔡静
Thanks
Page 8
辽宁师范大学
蔡静
9.3 条件编译
指定满足某条件才能对指定语句进行编译,称为条件编译。 几种形式: 程序段2】 程序段 】 #endif
#ifndef 标识符 程序段1 程序段 【#else 程序段2】 程序段 】 #endif
#if 表达式 程序段1 程序段 【#else 程序段2】 程序段 】 #endif
Page 5
辽宁师范大学
蔡静
二、带参数的宏替换/宏定义 带参数的宏替换 宏定义
格式: #define 宏名 形参表 宏名(形参表 形参表) 例:#define S(M, N) M*N
字符串
说明: 带参数的宏定义不是进行简单字符串替换,还要进行参数 替换。形参表列中的参数出现在字符串中。 宏展开只是将程序语句中宏名后括号内的实参代替 #define命令中的形参,并不计算。 宏名与其后括号间不能有空格。 例9.3-9.5:

预处理命令

预处理命令

二、表演区 (一)什么是表演区 表演区以幼儿表演游戏为设计核心,通过道具吸引幼儿积极参加故事表 演、游戏等活动。 (二)表演区的环境布置与材料投放 表演区可以分为固定式和活动式表演区角两类。 固定式的表演区角是指在活动室内辟出一定区域,存放表演所需要的用 具。 活动式的表演区角则是根据表演需要,临时在走廊、门厅、过道或室外 等地方设置表演场所,便于及时放置和收拢。
第9章 预处理命令
• 9. 1 概述 • 9. 2 宏定义 • 9. 3 文件包含 • 9. 4 条件编译
9. 2 宏定义
• 9. 2. 1 无参宏定义
• 无参宏的宏名后不带参数。 • 其定义的一般形式为 • #define 标识符字符串 • 其中, #表示这是一条预处理命令; 凡是以#开头的指令均为预处理命
果果:“老师,一分钟是多久呢?” 教师:“就是一会儿,我一转身。” 贝贝:“我知道,最细的秒针走一圈,挺长的。” 佳佳:“一分钟就是我们从门口走到后面的窗子那里。” 教师:“一分钟能做什么?” 佳佳:“给花浇水。” 果果:“唱完一首歌。” 贝贝:“搬来一把椅子。”……
学习目标
1. 了解幼儿日常交谈的主要特点及指导要求。 2. 掌握语言区角的环境布置与材料投放要求,能科学地开展语言区角活 动的指导。 3. 学会设计听说游戏的玩法,并能评析幼儿园听说游戏。
上一页 下一页 返回
9. 2 宏定义
• 【例9 - 2】不作宏代换程序举例。
上一页 下一页 说明: • 虽然已定义宏名OK 表示100, 但在printf 语句中OK 被引号括起来, 因
此不作宏代换。 • 程序的运行结果为“OK”, 这表示把“OK” 当字符串处理。
上一页 下一页 返回
义时, 必须十分注意, 应保证在宏代换之后不发生错误。

.net 预处理详解

.net 预处理详解

.net 预处理详解在使用.net框架进行软件开发时,我们经常会遇到需要在编译阶段对代码进行预处理的情况。

预处理是指在编译代码之前,通过指定一些预处理指令来控制代码的编译过程。

预处理指令在代码中以`#`符号开头,告诉编译器应该如何处理代码。

在本文中,我们将详细介绍.net 框架中常用的预处理指令及其用法。

1. 条件编译条件编译是预处理中最常用的功能之一,它可以根据一些条件来决定是否编译一段特定的代码。

通过使用`#if`和`#endif`指令,我们可以在代码中嵌入任意条件来控制编译过程。

例如,我们可以使用条件编译来根据不同的操作系统平台编译不同的代码片段:```csharp#if WINDOWSConsole.WriteLine("This is a Windows platform.");#elif LINUXConsole.WriteLine("This is a Linux platform.");#endif```上述代码中,`#if`指令用于判断是否为Windows平台,如果是则输出相应的信息;`#elif`指令用于判断是否为Linux平台,如果是则输出相应的信息。

通过条件编译,我们可以根据具体情况选择性地编译代码,以实现更好的跨平台兼容性。

2. 定义常量预处理指令还可以用于定义常量,在编译过程中将其替换为指定的值。

通过`#define`指令可以定义一个常量,并在代码中使用该常量。

例如:```csharp#define MAX_VALUE 100int value = MAX_VALUE;```上述代码中,我们使用`#define`指令定义了一个名为`MAX_VALUE`的常量,并将其设置为100。

之后,在代码中使用该常量时,编译器会将其替换为实际的值。

这样可以提高代码的可读性和维护性。

3. 跳过代码有时候,在调试或者测试代码时,我们需要暂时跳过一些代码片段而不编译它们。

预处理命令

预处理命令

3
math.h——文件包含数学程序。 reg51.h——文件中包含51单片机的特殊寄存器定义。 reg52.h——文件中包含52单片机的特殊寄存器定义。 setjmp.h——文件包含定义jmp_buf类型和setjmp和longjmp程序原型。 stdarg.h——文件包含可变长度参数列表程序。 stdlib.h——文件包含存储区分配程序。 stdio.h——文件包含标准输入和输出程序。 string.h——文件包含字符串操作程序、缓冲区操作程序。 对于51单片机而言,源程序开头必须要包含reg51.h头文件,因为该文件对51单片 机的相关位及寄存器进行了定义,这样在程序中才可以正常使用寄存器等资源。
#else 程序段2
#endif 若常量表达式成立,则编译程序1,否则编译程序2。
5
单片机原理及应用
单片机原理及应用
C51语言中提供了各种预处理命令,其作用类似于汇编程序中的伪指令。在编译环 境对源程序进行编译前,需要先对程序中的预处理命令进行处理,然后将处理结果和源 程序一起编译。C51语言中的预处理命令包括宏定义命令、文件包含命令和条件编译命 令等。通常,除条件编译命令外,预处理命令一般放在函数体之外,并且通常都放置在 源文件的开头。
句如下:
outputs=0xff;
/*输出 1111 1111 */
进行编译时,预处理器会将整个程序中的所有outputs替换为P2。
2.文件包含命令
#include命令的功能是将指定的定义或声明文件放入程序之中,该命令常用于引入 标准库函数文件。下面是一些常用的C51头文件:
absacc.h——包含允许直接访问8051不同存储区的宏定义。 assert.h——文件定义宏,用来建立程序的测试条件。 ctype.h——包含字符转换和分类程序。 intrins.h——文件包含指示编译器产生嵌入式固有代码的程序原型。

C语言程序设计教案 第九章 编译预处理

C语言程序设计教案  第九章 编译预处理

第九章编译预处理课题:第九章编译预处理教学目的:1、了解预处理的概念及特点2、掌握有参宏与无参宏的定义及使用,领会文件包含的使用及效果教学重点:教学难点:掌握宏的使用,文件包含有参宏与无参宏的使用步骤一复习引导ANSI C标准规定可以在C源程序中加入一些“预处理命令”,以改进程序设计环境,提高编程效率。

这些预处理命令是由ANSI C统一规定的,但它不是C语言本身的组成部分,不能直接对它们进行编译。

必须在对程序进行通常的编译之前,先对程序中这些特殊的命令进行“预处理”,即根据预处理命令对程序作相应的处理。

经过预处理后程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。

步骤二讲授新课C语言与其他高级语言的一个重要区别是可以使用预处理命令和具有预处理的功能。

C 提供的预处理功能主要有以下三种:宏定义、文件包含、条件编译。

分别用宏定义命令、文件包含命令、条件编译命令来实现。

为了与一般C语句相区别,这些命令以符号“ #” 开头。

§9.1宏定义宏:代表一个字符串的标识符。

宏名:被定义为“宏”的标识符。

宏代换(展开):在编译预处理时,对程序中所有出现的“宏名”,用宏定义中的字符串去代换的过程。

一、不带参数的宏定义一般形式:#define 标识符字符串#define PI 3.1415926main(){ float l, s, r, v;printf( “input radius:” );scanf( “%f”, &r );l = 2.0*PI*r;s = PI*r*r;v = 3.0/4*PI*r*r*r;printf(“%10.4f,%10.4f,%10.4\n”, l, s, v);}例如:由键盘输入y值,求表达式:3(y2+3y)+ 4(y2+3y)+ y(y2+3y)#define M (y*y+3*y)main(){ int s, y;printf( “Input a number :”); scanf (“%d”,&y);s=3*M+4*M+y*M; p rintf(“s=%d\n”,s);}先宏展开:s=3*(y*y+3*y) +4*( y*y+3*y) + y*(y*y+3*y)再与源程序合并说明:⑴宏名一般用大写表示,以便与变量名区分。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第9章预处理命令
宏定义不是C语句,所以不能在行尾加分号。

如果加了分号则会连分号一起进行臵换。

可以用#undef命令终止宏定义的作用域。

对程序中用“”括起来的内容(即字符串内的字符),即使与宏名相同,也不进行臵换。

宏定义只做字符替换,不分配内存空间。

宏名不是变量,不分配存储空间,也不能对其进行赋值。

在宏展开时,预处理程序仅对宏名作简单的字符串替换,不作任何检查。

在进行宏定义时,可以引用已定义的宏名
无参宏定义的一般格式:
#define 标识符字符串
将这个标识符(名字)称为“宏名”,在用预编译时将宏名替换成字符串的过程称为“宏展开”。

#define是宏定义命令。

带参宏定义的一般格式:
#define 宏名(形参表)字符串
带参宏的调用和宏展开:
调用格式:宏名(实参表);
宏展开(又称为宏替换)的方法:用宏调用提供的实参直接臵换宏定义中相应的形参,非形参字符保持不变。

定义有参宏时,宏名与左圆括号之间不能留有空格。

否则,C编译系统会将空格以后的所有字符均作为替代字符串,而将该宏视为无参宏。

有参宏的展开,只是将实参作为字符串,简单地臵换形参字符串,而不做任何语法检查。

为了避免出错,可以在所有形参外,甚至整个字符串外,均加上一对圆括号。

如: #define S(r) 3.14*(r)*(r)
则:area=S(a+b); 展开后为: area=3.14*(a+b)*(a+b);
调用有参函数时,是先求出实参的值,然后再复制一份给形参。

而展开有参宏时,只是将实参简单地臵换形参。

函数调用是在程序运行时处理的,为形参分配临时的内存单元;而宏展开则是在编译前进行的,在展开时不分配内存单元,不进行值的传递,也没有“返回值”的概念。

调用函数只可得到一个返回值,而用宏可以设法得到几个结果。

在有参函数中,形参都是有类型的,所以要求实参的类型与其一致;而在有参宏中,形参和宏名都没有类型,只是一个简单的符号代表,因此,宏定义时,字符串可以是任何类型的数据。

使用宏次数多时,宏展开后源程序变长,因为每展开一次都是程序增长,而函数调用不会使源程序变长。

宏替换不占用运行时间,只占编译时间。

而函数调用则占用运行时间(分配单元、保留现场、值传递、返回)。

在程序中如果有带实参的宏,则按#define命令行中指定的字符串从左到右进行臵换。

如果字符串中包含宏中的形参,则将程序语句中相应的实参(可以是常量、变量或表达式)代替形参。

如果宏定义中的字符串中的字符不是参数字符,则保留。

通常如果调用库函数,则用< >,使用用户自己编写的文件,则用“”。

两种格式的区别仅在于:
⑴使用“”:系统首先到当前目录下查找被包含文件,如果没找到,再到系统指定的“包
含文件目录”去查找。

⑵使用< >:直接到系统指定的“包含文件目录”(include)去查找。

预编译时不作任何检查。

只有编译已被宏展开后的源程序时才会发现语法错误并报错。

通常情况下,源程序中所有的行都参加编译,但有时希望对其中一部分内容只在满足一定条件才进行编译,则需要用到条件编译。

(1)一般格式
#ifdef 标识符
程序段1;
#else
程序段2;
#endif
它的作用是若指定的标识符已经被#define命令定义过,则在程序编译阶段编译程序段1,否则,编译程序段2.。

其中,#else部分可以没有。

2)#ifndef 标识符
程序段1
#else
程序段2
#endif
它的作用是若指定的标识符未被#define命令定义过,则在程序编译阶段编译程序段1,否则,编译程序段2.。

(3)#if 表达式
程序段1
#else
程序段2
#endif
它的作用是当指定的表达式的值为真(非零),则在程序编译阶段编译程序段1,否则,编译程序段2.。

(1) 一个#include命令只能指定一个被包含文件,如果要包含n个文件,要用n个#include 命令。

(2) 如果文件1包含文件2,而在文件2中要用到文件3的内容,则可在文件1中用两个include命令分别包含文件2和文件3,而且文件3应出现在文件2之前,即在file1.c中定义。

(3) 在一个被包含文件中又可以包含另一个被包含文件,即文件包含是可以嵌套的。

(4) 在#include命令中,文件名可以用双撇号或尖括号括起来。

(5) 被包含文件(file2.h)与其所在的文件(即用#include命令的源文件file2.c),在预编译后已成为同一个文件(而不是两个文件)。

因此,如果file2.h中有全局静态变量,它也在file1.h 文件中有效,不必用extern声明。

如果需要修改程序中常用的一些参数,可以不必修改每个程序,只需将这些参数放在一个头
文件中,在需要是修改头文件即可,但,被包含文件修改后,凡包含此文件的所有文件都要全部重新编译。

相关文档
最新文档