C语言预处理(高阶篇二十九)

  宏定义

    格式:

      #define 标识符 字符串

    如:

      #define  PI  3.1415926

    以后程序一看见PI,就自动会用3.1415926替代。

    注意:

    ※宏命令只是简单地替换字符串,但是它不做合法性检查。比如将3.1415926写成3.14T5926,只会在使用了PI的语句上报错,而不会在#define这行上报错。

    ※宏定义后面不得加分号

    ※宏定义后面的字符串可以省略。

    如:

      #define  PI

    ※可以直接用宏定义一条语句。

    如:

      #define PT printf(“%d\n”,a)

    以后就可以用PT来代替printf(“%d\n”,a)这条语句。

 

    ※在进行宏定义时,可以引用已定义的宏名,可以层层置换

      #define  R  3.0

      #define  PI  3.1415926

      #define  L  2*PI*R

      #define  S  PI*R*R

      main()

      {

        printf(“L=%f\nS=%f\n”,L,S);

      }

      运行情况如下:

      L=18.849556

      S=28.274333

    ※在字符串中的如果出现与宏名相同的字符串,不进行替换,如上面双引号中的L会原样输出。

    ※在学习宏命令时,一定要学会将它展开,再参与运算。如上面的printf函数层层展开,最后为:

      printf(“L=%f\nS=%f\n”,2*3.1415926*3.0,3.1415926*3.0*3.0);

    

    ※宏定义和普通变量不同,它不分配内存空间

    ※宏名称虽然没有规定非用大写,但是在C程序员的书写习惯当中,经常使用大写,以区分它与普通变量和函数。

  逻辑值

    程序员可以自己用#define来定义TRUE和FALSE来增加程序的可读性。

    ※NULL在系统中已经被定义成#define  NULL  0,EOF在系统中已经被定义成#define  EOF  -1

    这样,在判断指针是否为空时,if(pi!=NULL)与if(pi)就没有什么分别。

    那么,打开文件是否出错的代码可以缩减为:

      if(!(fp=fopen(“file_a”,”r”))){……}

  带参数的宏定义

    宏定义也可以加上参数,这时它的功能有点类似函数,但是它和函数有本质上的区别。

    格式:

      #define  宏名(参数表)  字符串

      如:

        #define  MUL(a,b)  a*b

        c=MUL(3,5);

        展开得c=3*5;

         

    ※也可在参数表中代入复杂点的字符串。如:

        c=MUL(2+3,1+2);

        展开得:

        c=2+3*1+2;

 

    这行代码出现了问题:*号改变了两个参数的优先级,因此,一般带参宏替换的标准定义形式为:

      #define  c=MUL(a,b)  (a)*(b)

      上面的代码展开得:

      c=(2+3)*(1+2);

      这样展开的结果符合程序员意图。

    ※前面说过,还有一种方法可以使用“常量”,那就是用宏替换。

      #define  NUM  3

      main()

        {

          int a[NUM];

        }

     用宏替换来定义数组,也是可以的。

  什么叫“预处理”

    每个程序在编译前,计算机会预先干一些事:那就是碰到预处理指令时,将它展开,得到真正的代码。如上面的代码经过编译器预处理后,得到的可运行代码实际上是:

    main()

    {

      int a[3];

    }

    因此如果把#define NUM 3误写成#define NUM 3T,程序会在第3行报错。以此类推,如果在多个地方使用了NUM宏,编译器会在使用过NUM的行数上都报个错。

    如果误写成#define  NUM  3;(这里加了个分号)

      在使用的时候 3的后面也会加分号。   比如: int a[NUM];    就是   int a[3;]

  文件包含

    格式:

      #include “文件名”

      或

      #include <文件名>

    双引号一般用来包含用户文件名,尖括号一般用来包含系统自带的文件名。如stdio.h就是系统文件名,所以包含stdio.h时,就要用尖括号括起来。

    有了文件包含功能以后,将一个大程序划分成多个文件就成为可能。多个文件可同时让多个人编写,再用#include将其它人写好的文件包含进来即可使用,不用关心它的细节。

    程序1

      用多文件模式计算任意两数之间所有整数之和

// 29-1用多文件模式计算任意两数之间所有整数之和.c
//

#include <stdio.h>
#include "file1.h"   //自定义头文件

main()
{
    int a, b;
    printf("请输入两个整数:");
    scanf_s("%d%d",&a,&b);
    fun(a, b);
}


//下面是 file1.h 里面的代码

//#pragma once
//
//void fun(int begin, int end)
//{
//    int s = 0;
//    for (int i = begin; i <= end; i++)
//    {
//        s += i;
//    }
//    printf("%d+%d+%d+...+%d+%d = %d\n", begin, begin + 1, begin + 2, end - 1, end, s);
//}

    ※用#include包含的文件后缀一般是.h

    ※文件包含也可以嵌套

  

    

    用多文件模式计算n的阶乘

// 29-2用多文件模式计算n的阶乘.c

#include <stdio.h>
#include "file2.h"

main()
{
    int a = 1;
    printf("请输入一个大于0的整数,求其阶乘\n");
    scanf_s("%d", &a);
    printf("%d的阶乘是%d", a, fun(a));
}



// file2.h 代码

//#pragma once
//
////阶乘函数
//int fun(int a)
//{
//    int result = 1;
//    for (int i = 1; i <= a; i++)
//    {
//        result *= i;
//    }
//    return result;
//}
原文地址:https://www.cnblogs.com/httpcc/p/15502930.html