平地起C楼—第十一层《预处理详解》

在这里插入图片描述

🚩前言

在C语言中,除了之前的各种语句,还包括一种特殊语句——预处理语句。它不是实现程序的功能,而是给C语言编译系统提供信息。C语言提供的预处理语句主要包括宏定义、文件包含、条件编译等。

1. 宏定义

宏定义的作用就是用一个标识符表示一个需要用到的字符等。其可以分为带参和不带参的宏定义。一般根据程序需要来写宏定义。

1.1 无参宏定义

定义格式:[注意:没有分号]

#define <标识符> <字符串……>
//比如:
#define PI 3.1415926

#define用于定义宏的。
标识符:定义的宏的名字。
字符串:是指宏体,可以是常量、表达式等。
一般宏定义在源程序的开头、函数定义的外面,有效范围是从宏定义语句开始到源文件结束。

1.2 有参的宏定义

上述无参宏定义只能完成简单的替换数值操作,为了更加灵活,我们可以给宏定义带上参数。
定义格式:

#define 标识符(参数1,参数2,……) 字符串

例:计算圆的周长,用带参宏定义

//1、带参宏定义
#include<stdio.h>
#define PI 3.1415926//无参宏定义
#define COMP_CIR(x) 2*PI*x//有参宏定义
int main()
{
    double r=1.0;
    printf("圆的周长:2*PI*r=%f\n",COMP_CIR(r));
    return 0;
}

结果展示:
在这里插入图片描述

1.3 带参宏定义和带参函数的对比

基本操作 带参宏定义 带参函数
处理时间 预处理 编译+运行
参数类型 无类型 根据需要定义类型
参数传递 不分配内存,无传递 分配内存,实参带入形参
运行速度 相对较慢,因为函数的调用需要内存分配、参数传递、压栈、出栈等操作

因此,带参宏定义较为灵活,它在程序预处理时就执行了。相比于函数,宏定义更好些。但是需要注意参数替换问题:
比如下面代码:

//2、带参宏定义的替换问题
#include<stdio.h>
#define ABS(x) (x)>=0?(x):-(x)//求绝对值问题

double compAbs(double num)
{
    return num>=0?num:-num;
}
int main()
{
    double x=12,y=12;
    printf("ABS(++x)=%f\n",ABS(++x));//(++x)>=0?(++x):-(++X)
    printf("compAbs(++y)=%f\n",compAbs(++y));//13>=0?13:-13
    return 0;
}

结果展示:
在这里插入图片描述

1.4 取消宏定义

#undef指令就是取消宏定义的。
比如:

//3、取消宏定义
#include<stdio.h>
#define PI 3.14
int main()
{
    printf("%f\n",PI);
    #undef PI//取消后
    printf("%f\n",PI);//再次引用
    return 0;
}

结果展示:
在这里插入图片描述

2. 条件编译

条件编译:就是说,有些程序需要在一定条件下才编译的。详解如下:

2.1 #if……#else…#endif

#if……#else…#endif该指令是根据常数表达式决定某段代码是否需要编译。
格式如下:

#if 常数表达式
	程序段1;
#else
	程序段2;
#endif	

上面就是,编译器只会编译代码块1和2,若常数表达式条件成立,编译器会编译代码块1,否则编译代码块2;
实例如下:

//4、条件编译#if……#else…#endif
#include<stdio.h>
//宏定义
#define WIN32 0
#define x64 1
#define SYSTEM WIN32//通过改变这里进行条件编译
int main()
{
    //通过判断SYSTEM的值,输出程序支持的平台
    #if SYSTEM==WIN32
        printf("win32\n");
    #else
        printf("x64");
    #endif
    return 0;
}

结果展示:
在这里插入图片描述

2.2 #ifdef

在程序中,若想判断某个宏是否被定义,可以使用这个指令#ifdef,通常和#endif一起用。格式如下:

#ifdef <宏名>
	程序段1;
#else
	程序段2;
#endif

代码演示:

//5、#ifdef
#include<stdio.h>
#define DEBUG
int main()
{
    int i=5;
    #ifdef DEBUG
        printf("i=%d\n",i);
    #endif

    int j=10;
    #ifdef DEBUG
        printf("j=%d\n",j);
    #endif

    int sum=i+j;
    #ifdef DEBUG
        printf("i+j=%d\n",sum);
    #endif
    return 0;
}

结果展示:只有当DEBUG被定义了才会有输出的
在这里插入图片描述

2.3 #ifndef

#ifndef作用是:用来确定某一个宏是否未被定义,它和#ifdef意思相反。若宏没被定义才编译ifndef指令下的内容,否则就跳过。
格式:

#ifndef <宏名>
	程序段1;
#else
	程序段2;
#endif

代码演示:

//6、#ifndef
#include<stdio.h>
#define DEBUG
int main()
{
    #ifndef DEBUG
        printf("输出信息:\n");
    #else
        printf("无信息\n");
    #endif
    return 0;
}

结果展示:
在这里插入图片描述

3. #pragma

#pragma预处理的作用是:设置编译器的状态或者指示编译器完成特殊的功能。格式:

#pragma parameter

parameter表示:编译器特有的字段,常用的用法有下面几种:

格式 作用
#pragma warning 对编译器的警告处理
#pragma message 用于让编译器在编译过程中输出相应的信息
#pragma comment 通常用于连接库文件

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-30 04:12:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-30 04:12:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-30 04:12:02       87 阅读
  4. Python语言-面向对象

    2024-03-30 04:12:02       96 阅读

热门阅读

  1. C/C++ 一些使用网站收集...

    2024-03-30 04:12:02       42 阅读
  2. 【openGL4.x手册09】转换反馈

    2024-03-30 04:12:02       33 阅读
  3. 任务记录.

    2024-03-30 04:12:02       38 阅读
  4. 2024年最新github排行前100名项目

    2024-03-30 04:12:02       42 阅读
  5. for in 和 for of的区别

    2024-03-30 04:12:02       41 阅读
  6. 中台理念下的多应用场景平台构建与实践

    2024-03-30 04:12:02       43 阅读
  7. docker容器退出后数据丢失怎么恢复?

    2024-03-30 04:12:02       40 阅读
  8. 面试题:IoC容器的理解与实例化过程

    2024-03-30 04:12:02       39 阅读
  9. 【Python】如何入门 Python:系统化方法与实践路径

    2024-03-30 04:12:02       41 阅读
  10. 算法练习----力扣每日一题------1

    2024-03-30 04:12:02       48 阅读
  11. 阳光消费金融2023利润创新高,固收业务立功

    2024-03-30 04:12:02       40 阅读
  12. Gitea 的简单介绍

    2024-03-30 04:12:02       40 阅读
  13. C#——系统学习(LINQ)

    2024-03-30 04:12:02       40 阅读