Day22


C语言编译步骤

  • 预处理
  • 编译
  • 汇编
  • 链接

什么是预处理

        预处理就是在源文件(如.c文件)编译之前,所进行的一部分预备操作,这部分操作是由预处理程序自动来完成;当源文件在编译时,编译器会自动调用预处理程序来完成对预处理指令的解析,预处理指令解析完成才能进去下一步的编译过程。

        我们为了能够方便的看到这个编译细节,可以使用下面命令:

gcc 源文件 -E -o 程序名[.后缀]

预处理的功能

宏定义
  • 不带参数的宏定义

    语法:
    #define 宏名 常量数据

    预处理:此时的预处理只做数据替换,不做类型检查

    注意:我们定义的宏是不会占用内存空间的,还没有到编译环节,就已经被替换成了我们宏中的常量数据

    宏展开:在预编译时将宏名替换成字符串的过程称为“宏展开”

  • 案例:

    #include <stdio.h>
    #define PI 3.1415926
    void main()
    {
      float l, s, r, v;
      printf("input radius:");
      scanf("%f", &r);
      l = 2.0 * PI * r;
      s = PI * r * r;
      v = 4.0 / 3 * PI * r * r * r;
      printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n", l, s, v);
    }
  • 带参数的宏定义

    • 语法:

      #define 宏名(参数列表) 参数表达式
    • 面试题:

      #define multi(a,b)a * b
      /*
        宏定义:带参数
      */
      #include <stdio.h>
      #define MULTI(a, b) a *b // 7 + 2 * 3
      
      int main()
      {
        int result = MULTI(7 + 2, 3);
      
        printf("%d\n", result); // 13
      }

  • 宏定义的作用域

    • #define 命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。通常,#define命令写在文件开头,函数之前,作为文件一部分,在此文件范围内有效。

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

  • 案例:

    /*
      宏定义的作用域
    */
    #define PI 3.14
    #define DAY 20
    
    void fun()
    {
      float r = 4;
      float s = PI * r * r;
      int day = DAY;
    }
    
    #undef PI // 结束PI的范围
    
    #define PI 3.1415926
    void fun1()
    {
      float r1 = 4;
      float s1 = PI * r1 * r1;
      int day = DAY;
    }
    
    void main()
    {
      fun();
      fun1();
    }
    • 在宏定义中引用已定义的宏名
       
      • 案例:
        #include <stdio.h>
        #define R 3.0
        #define PI 3.1415926
        #define L 2 * PI *R
        #define S PI *R *R
        void main()
        {
          printf("L=%f\nS=%f\n", L, S);
        }

文件包含

概念

所谓“文件包含"处理是指一个源文件可以将另外一个源文件的全部内容包含进来。这个适用于多文件开发。

预处理

此时的预处理,是将文件中的内容替换,文件包含指令。

包含方式

  • 第1种  :  #include <xxxx.h>
     
  • 系统会到标准库头文件目录( Linux下 /usr/include )查找包含的文件
     
  • 第二种:#include "xxxx.h"

    在当前工程路径下查找,如果未找到,仍然会到标准库头文件目录查找
     
  • 案例:

    head.h
    /*
      自定义头文件,专门用于存放被外部访问的函数的声明
    */
    
    // 数组累加和计算
    extern int sum(const int *p, int len);

    5.c

    /*
      实现数组元素的累加计算
    */
    int sum(const int *p, int len)
    {
      int sum = 0;
      register int i = 0;
    
      for (; i < len; i++)
      {
        sum += *(p + i);
      }
      return sum;
    }

    6.c

    #include <stdio.h>
    // 引用自定义头文件
    #include "head.h"
    
    // 如果有n多个外部函数,
    //  引入外部函数
    // extern int sum(const int *, int);
    
    int main()
    {
      int a[5] = {12, 33, 14, 55, 34};
    
      int res = sum(a, 5);
    
      printf("数组累加结果:%d", res);
      return 0;
    }
    

    编译命令:

    gcc 5.c 6.c -o 56 //包含关系的c文件要一起编译



     

条件编译

概念

根据设定的条件选择待编译的语句代码。

预处理

将满足条件的语句进行保留,不满足条件的语句进行删除,交给下一步编译

语法

语法一:

#ifdef 标识 -- 判断标识符定义或未定义
    ..
#else
    ..
#endif

语法二:

#ifndef 标识 -- 判断标识符定义或未定义
    ..
else
    ..
#endif

语法三:

#if 表达式 -- 根据表达式返回的结果:0-不成立,1-成立
    ..
#else
    ..
#endif

案例1:

/**
 * 预处理-条件编译
 */
#define MINUS 1
int main(void)
{
#ifndef MINUS // 判断标准是:标识有没有被定义
  int a = 7 - 4;
#else
  int a = 7 * 4;
#endif
  printf("计算结果:%d\n", a);
  return 0;
}

案例2:

/*
  预处理-条件编译:输入一行字母字符,
  根据需要设置条件编译,
  使之能将字母全改为大写输出,
  或全改为小写字母输出。
*/

#include <stdio.h>

// 定义一个标识
#define LETTER 1

void main()
{
  // 测试用的字符数组
  char str[20] = "C Language";
  char c;

  int i = 0;

  while ((c = str[i]) != '\0')
  {
    i++;
#if LETTER
    if (c >= 'a' && c <= 'z')
    {
      c -= 32;
    }
#else
    if (c >= 'A' && c <= 'Z')
    {
      c += 32;
    }
#endif
    printf("%c", c);
  }
  printf("\n");
}

避免头文件重复包含的方法

语法:

#ifndef __XXXX_H
#define __XXXX_h
    ...
#endif

案例:

/**
* 自定义头文件,专门用于存放被外部访问的函数的声明
*/
#ifndef __ALGORITHM_H
#define __ALGORITHM_H
// 数组的累加和计算
extern int sum(const int *p,int len);
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值