zoukankan      html  css  js  c++  java
  • 预处理器之 define

    编译一个C程序涉及很多步骤。其中第一步骤被称为预处理阶段。C预处理器在源代码编译之前对其进行一些文本性质的操作。它的主要任务包括删除注释、插入被#include指令包含的内容、定义和替换由#define指令定义的符号及确定代码的部分内容是否应该根据一些条件编译指令进行编译。

    #define

    1.#define  name  stuff

    有这条指令以后,每当有符号name出现在这条指令之后,预处理器就会把它替换成stuff。

    2.#define    DEBUG_PRINTF    printf(" File output ");

    这条指令后面加了一个封号。

    如果出现以下代码

    if(  .....   )

      DEBUG_PRINTF;

    else( .....)

       ......

    那么这部分代码的详解是

    if(  .....   )

      printf(" File output ");

      ;

    else( .....)

       ......

    在if之后不是else 而是另外的一条空白语句。这样就会给程序带来一个很隐蔽的错误(及其不容易被发现)。

    3.宏:#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏或定义宏

    #define    name(parameter-list)      stuff

    这里的name和(parameter-list)之间不得有任何空白存在,否则(parameter-list)会被解释成为stuff的一部分。

    #define    square(x)       x*x

    int a = 5

    printf("%d ",square(a+1));

    那么程序会输出多少。

    乍一看会觉得是36,其实是11。宏是简单的文本替换,那么square(a+1)  表示  a+1*a+1 

    ps:宏只是简单的文本替换,和函数是有本质的区别,不能当作函数来使用

    4.#define替换

    ①.调用宏时,首先参数进行检查,看看是否包含了任何由#define定义的符号,如果是,它们首先被替换。

    ②.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被它们的值所替代。

    ③.最后,再次对结果文本进行扫描,看看它是否包含了任何由#define定义,如果是,就重复上述处理过程。

    当预处理器搜索#define定义的符号时,字符串常量的内容并不进行检查,如果想把宏参数插入到字符串常量中,可以使用2种技巧。首先,邻近字符串自动连接的特性使我们容易把一个字符串分成几段,每段实际上都是一个宏参数。这里有一种这种技巧的例子:

    #define  PRINT( FORMAT,  VALUE )     

          printf( "The value is "FORMAT" ", VALUE)

    ........

    int x=5;

    PRINT(  "%d",  x+3 );

    输出结果是:  The value  is  8

    这种技巧只有当字符串常量作为宏参数时才能使用。

    第二个技巧使用预处理器把宏参数转换成一个字符串。#argument 这种结构被预处理器翻译为“argument”。这种翻译让你像下面这样编写代码:

    #define  PRINT( FORMAT, VALUE )    

          printf( "The value of " #VALUE " 

           is  "FORMAT" ",VALUE)

    .......

    int x=5;

    PRINT( "%d",  x+3 );

    它将产生下面结果:

    The value of x+3 is 8

    5.宏与函数

    宏频繁的用于执行简单的计算,比如在2个表达式中寻找较大的一个

    #define    MAX( a, b)     (  (a) > (b) ? a:b )

    但为什么不用函数来完成任务呢?

    ①. 用于调用函数和从函数返回的代码很可能比实际执行这个计算的代码更大。所以使用宏比使用函数在程序的规模和速度方面都更胜一筹

    ②.函数的参数必须声明为一种特定的类型,所以它只能在类型合适的表达式上使用。反之,宏可以用于整型、浮点型。换句话说,宏是与类型无关的。

    ③.还有些任务根本无法用函数完成,如下:

    #define   MALLOC( n, type )   

         (     (type *)malloc(  (n) * sizeof( type ) )    )

    这个宏的第二个参数时一种类型,它无法作为函数参数进行传递。

     pi = MALLOC( 25, int )

     pi = ( int  *)malloc( 25 * sizeof(int) )

    6.带副作用的宏参数

    当宏参数在宏定义中出现的次数超过一次时,如果这个参数具有副作用,那么当你使用这个宏时就可能出现危险,导致不可预料的结果。副作用就是在表达式求值时出现的永久性效果。例如

         x+1  这个表达式可以重复执行上百次,它每次获得的结果都是一样的。这个表达式没有副作用,但

          x++就具有副作用:它增加x的值,每当这个表达式执行一次,结果就改变一次。

    例如下面代码,会输出什么?

    #define   MAX( a, b )  (a)>(b)?(a):(b)

    int    x  =  5;

    int    y  =  8;

    int    z  =  MAX( x++, y++ );

    printf( "x = %d     y = %d    z = %d ",x,y,z);

    结果是 x=6, y = 10 , z = 9

    分析:z = (  x++  ) > (  y++ )  ?   ( x++ ) : ( y++ )

    第一个表达式是条件表达式:这里 x自增一次,y自增一次

    第二个是赋值表达式:赋值完成后大一些的变量也就是y自增一次。 所以x=6, y=10。

    总结:这次关于define的用法总结的算是比较全面的一篇的文章了

     

  • 相关阅读:
    新年后的第一个学习总结
    2021/02/07周学习总结
    内网穿透
    有效的括号
    实现一个简单的模板字符串替换
    二叉树的最大深度
    前端性能和错误监控
    前端缓存
    display: none; opacity: 0; visibility: hidden;
    发布订阅模式与观察者模式
  • 原文地址:https://www.cnblogs.com/ATMvip/p/3226748.html
Copyright © 2011-2022 走看看