0%

C语言预处理

间歇性努力,网络流行语,一种只要看到鸡血文/鸡汤文,就会偶尔努力一下,以掩盖自己内心不安的生活方式。常用作间歇性努力,持续性颓废,或间歇性努力,持续性一事无成。

一、概念

      为了改进程序,提高程序编程效率,我们可以在C程序中加入一些“预处理命令”。预处理命令是由ANSI(美国国家标准学会)统一规定的,用来向C语言编译系统提供信息,通知C编译器对源程序进行编译之前应该做哪些预处理工作。预处理命令不是C语言本身的组成部分,不能直接对它们进行编译。必须在对C程序进行正常编译之前,对预处理命令进行“预处理”。例如程序中常用的#include<stdio.h>就是一个预处理命令,在编译C程序之前,用stdio.h文件中的实际内容代替该内容,然后再对程序进行正常编译。经过预处理后,程序中就不再包含预处理命令了,最后再由编译器对预处理后的源程序进行通常的编译处理,得到可供执行的目标代码。

为了区别预处理命令与其他的C语句,所有的预处理命令均以#开头,占独立的一行,且语句结尾不用分号;结束。

二、分类

  1. 宏定义:是指用一个指定的标识符来定义一个字符序列,根据宏定义是否有参数将宏定义分为两种:不带参数的宏定义和带参数宏定义。
    • 不带参数的宏定义:不带参数的宏定义是用一个指定的标识符来代表一个字符串,一般形式为:#define 标识符 字符串,标识符为所定义的宏名,字符串可以是常量、表达式、格式串等。
      • 在预编译时将宏名替换成字符串的过程称为宏展开
      • 宏定义是用宏名代替一个字符串,不做正确性检查
      • 如果在程序中出现用双引号括起来的字符串内包含有与宏名相同的名字,预编译时并不进行宏替换
      • 宏定义是专门用于预处理命令的,它与变量不同,并不占用内存空间。
    • 带参数宏定义:C语言允许宏带有参数,在宏定义中的参数称为形式参数。带参数的宏定义不是进行简单的字符串代换,而是进行参数替换,一般形式:#define 标识符(形式参数表列) 字符串

和函数的区别:

  • 函数在定义和调用中所使用的形式参数和实际参数都受到数据类型的限制,而带参数宏的形式参数和实际参数可以是任意数据类型。
  • 函数调用时是先计算实际参数表达式的值,然后代入形式参数。而宏定义展开时,只是替换。
  • 函数调用时,编译系统会为其分配内存单元,而宏展开时系统不会为其分配内存单元,宏展开也没有“返回值”的概念。
  • 多次使用宏,宏展开后源程序增长,而函数调用不会使源程序增长。
  • 函数只能有一个返回值,而用宏可以设法得到多个值。
  1. 文件包含:是指一个源文件将另一个源文件的全部内容包含进来。其一般形式为:#include <文件名>#include "文件名"

    • 如果采用第一种形式,编译系统将在系统指定的路径(即C库函数头文件所在的子目录)下搜索文件
    • 如果采用第二种形式,编译系统首先会在用户当前工作的目录中搜索要包含的文件,如果找不到,再按系统指定的路径搜索
    • 编译时,并不是分别对两个文件进行编译,然后再将它们的目标程序连接,而是在经过编译预处理后将头文件包含到主文件中,得到一个新的源程序,然后再对新的源程序进行编译。因此如果被保护文件中有全局静态变量,它也在新源程序中有效,不必用extern声明。
    • 文件头部被包含的文件常以“.h”作为后缀名,当然用其他的后缀名甚至没有后缀名也是可以的。
    • 文件除了可以包含函数原型和宏定义外,还可以包括结构体类型定义和全局变量等。
  2. 条件编译:一般情况下C源程序中所有行都参与编程,但有时希望部分代码只是在满足一定条件时才进行编译,形成目标代码。这种对程序的一部分内容指定编译的条件成为条件编译。

三、参考