zoukankan      html  css  js  c++  java
  • C说话教程第九章:预处理(1)

    预处理

    概述
      在后面各章中,已屡次运用过以“#”号开头的预处理饬令。如包孕饬令# include,宏定义饬令# define等。在源法度中这些饬令都放在函数之外, 而且伟大都放在源文件的后面,它们称为预处理部门。

      所谓预处理是指在中缀编译的第一遍扫描(词法扫描和语法分析)之前所作的事故。预处理是C说话的一个首要听命, 它由预处理法度卖力完成。当对一个源文件中缀编译时, 系统把主动援用预处理法度对源法度中的预处理部门作处理, 处理截止主动进入对源法度的编译。

      C说话提供了多种预处理听命,如宏定义、文件包孕、 前提编译等。公正地运用预处理听命编写的法度便于阅读、编削、 移植和调试,也有利于模块化法度计划。本章引见常用的几种预处理听命。

    宏定义
      在C说话源法度中允许用一个标识符来走漏显示一个字符串, 称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对法度中扫数泛起的“宏名”,都用宏定义中的字符串去代换, 这称为“宏代换”或“宏睁开”。

      宏定义是由源法度中的宏定义饬令完成的。 宏代换是由预处理法度主动完成的。在C说话中,“宏”分为有参数和无参数两种。 上面告别讨论这两种“宏”的定义和调用。

    无参宏定义
      无参宏的宏名后不带参数。其定义的伟大方法为: #define 标识符 字符串 其中的“#”走漏显示这是一条预处理饬令。平常以“#”开头的均为预处理饬令。“define”为宏定义饬令。 “标识符”为所定义的宏名。“字符串”可以是常数、表达式、样式串等。在后面引见过的符号常量的定义就是一种无参宏定义。 别的,常对法度中几回运用的表达式中缀宏定义。例如: # define M (y*y 3*y) 定义M表达式(y*y 3*y)。在编写源法度时,扫数的(y*y 3*y)都可由M庖代,而对源法度作编译时,把先由预处理法度中缀宏代换,即用(y*y 3*y)表达式去置换扫数的宏名M,然后再中缀编译。
    #define M (y*y 3*y)
    main(){
    int s,y;
    printf("input a number: ");
    scanf("%d",&y);
    s=3*M 4*M 5*M;
    printf("s=%d\n",s);
    }
      上例法度中起首辈行宏定义,定义M表达式(y*y 3*y),在s= 3*M 4*M 5* M中作了宏调用。在预处理时经宏睁开后该语句变为:s=3*(y*y 3*y) 4(y*y 3*y) 5(y*y 3*y);但要详细的是,在宏定义中表达式(y*y 3*y)单方的括号不克不及少。不然会发生发火错误。
      当作以下定义后: #difine M y*y 3*y在宏睁开时把失踪失踪下述语句: s=3*y*y 3*y 4*y*y 3*y 5*y*y 3*y;这相称于; 3y2 3y 4y2 3y 5y2 3y;显然与原题意要求不符。计较成就虽然是错误的。 是以在作宏定义时必需很是详细。应保证在宏代换之后不发生发火错误。关于宏定义还要说明');以下几点:

    1. 宏定义是用宏名来走漏显示一个字符串,在宏睁开时又以该字符串庖代宏名,这只是一种简略的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理法度对它不作任何搜查。如有错误,只能在编译已被宏睁开后的源法度时发明。

    2. 宏定义不是说明');或语句,外行末不用加分号,如加上分号则连分号也一同置换。

    3. 宏定义必需写在函数之外,其感导域为宏定义饬令起到源法度结 束。如要中缀其感导域可运用# undef饬令,例如: # define PI 3.14159
    main()
    {
    ……
    }
    # undef PIPI的感导域
    f1()
    ....走漏显示PI只在main函数中有效,在f1中有效。
    4. 宏名在源法度中若用引号括起来,则预处理法度分歧错误其作宏代换。
    #define OK 100
    main()
    {
    printf("OK");
    printf("\n");
    }
    上例中定义宏名OK走漏显示100,但在printf语句中OK被引号括起来,是以不作宏代换。法度的运转成就为:OK这走漏显示把“OK”当字符串处理。

    5. 宏定义允许嵌套,在宏定义的字符串中可以运用已经定义的宏名。在宏睁开时由预处理法度层层代换。例如: #define PI 3.1415926
    #define S PI*y*y /* PI是已定义的宏名*/对语句: printf("%f",s);在宏代换后变为: printf("%f",3.1415926*y*y);

    6. 习气上宏名用大写字母走漏显示,以便于与变量区别。但也允许用小写字母。

    7. 可用宏定义走漏显示数据范例,使誊写利便。例如: #define STU struct stu在法度中可用STU作变量说明');: STU body[5],*p;#define INTEGER int 在法度中即可用INTEGER作整型变量说明');: INTEGER a,b; 应详细用宏定义走漏显示数据范例和用typedef定义数听说明');符的区别。宏定义只是简略的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简略的代换, 而是对范例说明');符重新命名。被命名的标识符具有范例定义说明');的听命。请看上面的例子: #define PIN1 int* typedef (int*) PIN2;从方法上看这两者相似, 但在幻想运用中却不相反。上面用PIN1,PIN2说明');变量时就可以看出它们的区别: PIN1 a,b;在宏代换后酿成 int *a,b;走漏显示a是指向整型的指针变量,而b是整型变量。但是:PIN2 a,b;走漏显示a,b都是指向整型的指针变量。因为PIN2是一个范例说明');符。由这个例子可见,宏定义虽然也可走漏显示数据范例, 但毕竟是作字符
    代换。在运用时要非分不凡小心,以避蜕化。

    8. 对“输入样式”作宏定义,可以增长誊写费事。例9.3 中就回收了这种举措。
    #define P printf
    #define D "%d\n"
    #define F "%f\n"
    main(){
    int a=5, c=8, e=11;
    float b=3.8, d=9.7, f=21.08;
    P(D F,a,b);
    P(D F,c,d);
    P(D F,e,f);
    }




    版权声明: 原创作品,允许转载,转载时请务必以超链接方法标明文章 原始因由 、作者信息和本声明。不然将清查划定规矩责任。

  • 相关阅读:
    build.gradle文件详解<转> 推荐
    openGL 环境配置
    手写 大整数
    FOJ有奖月赛-2016年8月(daxia专场之过四题方有奖)
    2.1 基本计数方法
    第7章 代码
    第7章 高级数据结构的编程实验
    3.3 字符串(1)
    2016_NENU_CS_3
    3.2 区间信息的维护与查询
  • 原文地址:https://www.cnblogs.com/zgqjymx/p/1975572.html
Copyright © 2011-2022 走看看