c语言define不带后面的语句
    #define是c语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 c语言的学习很不利。
    1. #define命令剖析
    #define命令就是c语言中的一个宏定义命令,它用以将一个标识符定义为一个字符串,该标识符被称作宏名,被定义的字符串称作替代文本。
    该命令有两种格式:一种是简单的宏定义,另一种是带参数的宏定义。
    (1)  直观的宏定义:
    #define  <宏名>  <字符串>
    基准:  #define pi 3.
    (2) 带参数的宏定义
    #define  <宏名> (<参数表>)  <宏体>
    例: #define  a(x) x
    一个标识符被宏定义后,该标识符就是一个宏名。这时,在程序中发生的就是宏名,在该程序被编程前,先将宏名用被定义的字符串替代,这称作宏替代,替代后才展开编程,宏替代就是直观的替代。
    1.2 宏替换发生的时机
    为了能真正认知#define的促进作用,使我们去介绍一下对c语言源程序的处理过程。当我们在一个内置的研发环境如turbo c中将撰写不好的源程序展开编程时,实际经过了预处理、编程、编订和相连接几个过程,见到图1。
    源程序预处理器修改后的源程序编译器汇编程序汇编器可重定位的目标程序连接器可执行的目标程序图1 c语言的编译过程
    其中进度表处理器产生编译器的输入,它同时实现以下的功能:
    (1)    文件包含
    可以把源程序中的#include 拓展为文件正文,即为把涵盖的.件出并进行至#include 所在处。
    (2)    条件编译
    进度表处理器根据#if和#ifdef等编程命令及其后的条件,将源程序中的某部分涵盖进去或确定出外,通常把确定出外的语句转换成空行。
    (3)    宏展开
    进度表处理器将源程序文件中发生的对宏的提及进行成适当的宏 定义,即为本文所说的#define的功能,由进度表处理器去顺利完成。
    经过预处理器处理的源程序与之前的源程序有所有不同,在这个阶段所进行的工作只是纯粹的替换与展开,没有任何计算功能,所以在学习#define命令时只要能真正理解这一点,
这样才不会对此命令引起误解并误用。
    2.1 直观宏定义采用中发生的问题
    在简单宏定义的使用中,当替换文本所表示的字符串为一个表达式时,容易引起误解和误用。如下例:
    基准1  #define  n  2+2
    void main()
    {
    int  a=n*n;
    printf(“%d”,a);
    }
    (1) 发生问题:在此程序中存有着宏定义命令,宏n代表的字符串就是2+2,在程序中存
有对宏n的采用,通常同学大二该程序时,难产生的问题就是先解n为2+2=4,然后在程序中排序a时采用乘法,即n*n=4*4=16,其实该题的结果为8,为什么结果存有这么小的偏差?
    (2)问题解析:如1节所述,宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生,在展开时是在宏n出现的地方 只是简单地使用串2+2来代替n,并不会增添任何的符号,所以对该程序展开后的结果是a=2+2*2+2,计算后=8,这就是宏替换的实质,如何写程序才 能完成结果为16的运算呢?
    (3)解决办法:将宇定义译成如下形式
    #define  n  (2+2)
    这样就可以替换成(2+2)*(2+2)=16
    2.2 带参数的宏定义出现的问题
    在拎参数的宏定义的采用中,极容易引发误会。比如我们须要搞个宏替代能求任何数的
平方,这就须要采用参数,以便在程序中用实际参数去替代宏定义中的参数。通常学生难译成如下形式:
    #define  area(x)  x*x
    这在采用中就是很难发生问题的,看看如下的程序
    void main()
    {
    int  y=area(2+2);
    printf(“%d”,y);
    }
    按理说给的参数就是2+2,税金的结果必须为4*4=16,但是弄错了,因为该程序的实际结果为8,仍然就是未能遵从单纯的直观替代的规则,又就是先排序再替代 了,在这道程
序里,2+2即为area宏中的参数,必须由它去替代宏定义中的x,即为替换成2+2*2+2=8了。那如果遵从(1)中的解决办法,把2+2 内加出来,即为把宏体中的x括出来,与否可以呢?#define  area(x) (x)*(x),对于area(2+2),替代为(2+2)*(2+2)=16,可以化解,但是对于area(2+2)/area(2+2)又可以怎么样 呢,有的学生一看见这道题马上得出结果,因为分子分母一样,又弄错了,还是忘了遵从先替代再排序的规则了,这道题替代后可以变成 (2+2)*(2+2)/(2+2)*(2+2)即4*4/4*4按照秦九韶运算规则,结果为16/4*4=4*4=16,那必须怎么呢?化解方法就是在整个 宏体上再加一个括号,即#define  area(x) ((x)*(x)),不要真的这没必要,没它,就是没用的。
    要想能够真正使用好宏定义,那么在读别人的程序时,一定要记住先将程序中对宏的使用全部替换成它所代表的字符串,不要自作主张地添加任何其他符号,完全展 开后再进行相应的计算,就不会写错运行结果。如果是自己编程使用宏替换,则在使用简单宏定义时,当字符串中不只一个符号时,加上括号表现出优先级,如果是 带参数的宏定义,则要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号。看到这里,不禁要问,用宏定义这么麻烦,这么容易出错,可不可以摒弃它, 那让我们来看一下在c语言中用宏定义的好处吧。
    3  宏定义的优点
    (1)  方便程序的修改
    采用直观宏定义需用宏替代一个在程序中经常采用的常量,这样在将该常量发生改变时,不必对整个程序展开修正,只修正宏定义的字符串即可,而且当常量比较短时, 我们可以用较短的存有意义的标识符去写下程序,这样更便利一些。我们所说的常量发生改变不是在程序运行期间发生改变,而是在编程期间的修正,握一个大家比较熟识的基准 子,圆周率π就是在数学上常用的一个值,有时我们会用3.14去则表示,有时也可以用3.等,这必须看看计算所须要的精度,如果我们基本建设的一个程序中 必须多次采用它,那么须要确认一个数值,在本次运转中不发生改变,但也许后来辨认出程序所整体表现的精度存有变化,须要发生改变它的值, 这就须要修正程序中所有的有关数值,这可以给我们增添一定的不便,但如果采用宏定义,采用一个标识符去替代,则在修正时只修正宏定义即可,还可以增加输出 3.这样短的数值多次的情况,我们可以如此定义 #define  pi  3.,既增加了输出又易于修正,何乐而不为呢?
    (2) 提高程序的运行效率
    采用拎参数的宏定义可以顺利完成函数调用的功能,又能够增加系统上开 订货,提升运转效率。正像c语言中所谈,函数的采用可以并使程序更加模块化,易于非政府,而且可以重复利用,但在出现函数调用时,须要留存调用函数的现场,以便子 函数继续执行完结后能够回到继续执行,同样在子函数继续执行回去后必须恢复正常调用函数的现场,这都须要一定的时间,如果子函数继续执行的操作方式比较多,这种切换时间开支可以忽 略,但如果子函数顺利完成的功能比较太少,甚至于只顺利完成一点操作方式,例如一个乘法语句的操作方式,则这部分切换开支就相对很大了,但采用拎参数的宏定义就不能发生这个问 题,因为它就是在预处理阶段即为展开了宏进行,在继续执行时不须要切换,即为在当地继续执行。宏定义可以顺利完成直观的操作方式,但繁杂的操作方式还是必须由函数调用去顺利完成,而且宏定义 所挤占的目标代码空间相对很大。所以在采用时必须依据具体情况去同意与否采用宏定义。
    形式参数不能用带引号的字符串替换。
    但是,如果在替代文本中,参数名以#做为后缀则结果将被拓展为 由 实际参数 替代 此实际参数的拎引号的字符串。
    例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:
    #define dprint(expr) printf(#expr “ = %\n”,expr)
    使用语句 dprint(x/y);
    调用宏时,该宏将被拓展为:printf(“x/y”“ = %\n”,x/y);
    其中的字符串被连接起来了,这样便等价于printf(“x/y = %\n”,x/y);
    在实际参数中,每个双引号 “ 将被替代为 \” ;反斜杠\将被替代为\\,因此替代后的字符串就是合法的字符串常量。
    预处理运算符 ## 为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与 ## 相邻,则该参数将被实际参数替换,##与前后的空白符将被删除,并对替换后的结果重新扫描。
    比如,下面定义的宏paste用作相连接两个参数
    #define paste(front, back) front ## back
c语言如何去学    因此,宏调用past(name,1)的结果将创建记号name1.
    c语言中没有swap这个函数,c语言不支持重载,也没有模版的概念,所以对于每一种类型,都要写出相应的swap,如
    intswap  (int  *,  int  *);
    longswap  (long  *,  long  *);
    stringswap  (char  *,  char  *);
    宏定义swap(t,x,y)以交换t类型的两个参数(要使用程序块结构)。
    程序如下:
    #include <iostreah>
    #define swap(t,x,y) \

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。