【C语言回顾】预处理

  • 前言
  • [1. 简单概要](#1. 简单概要)
  • [2. 预处理命令讲解](#2. 预处理命令讲解)
  • 结语


上期回顾: 【C语言回顾】编译和链接
个人主页:C_GUIQU
归属专栏:【C语言学习】

前言

各位小伙伴大家好!上期小编给大家讲解了C语言中的编译和链接,接下来我们讲解一下预处理!

1. 简单概要

  1. 预定义符号:在C语言等编程语言中,预定义符号是指在标准库或系统头文件中已经定义的常量、宏和字符串。这些符号通常用于表示特定的含义,如数学函数、字符串操作符等。预定义符号的使用可以帮助程序员简化代码编写,提高可读性。
  2. #define 定义常量:在C语言中,使用 #define 指令可以定义常量。常量是一种数据类型,其值一旦被确定就不能改变。通过 #define 定义的常量,可以在程序中的多个地方使用,而无需重复指定其值。
  3. #define定义宏:宏(macro)是C语言中的一个重要概念,它允许程序员定义一些文本块,这些文本块可以在程序的不同部分被多次使用。宏的定义通常以 #define 开始,后面跟一个标识符(通常是大写字母),然后是宏的参数列表。当宏被调用时,它会替换掉源代码中的宏名,并执行宏体中的代码。
  4. 带有副作用的宏参数:宏参数本身并不存储任何值,它们只是起到占位的作用。然而,有些宏可能会对编译器产生额外的操作或影响,这种宏被称为具有"副作用"的宏。例如,某些宏可能会改变控制流、执行算术运算或其他非纯函数行为。
  5. 宏替换的规则:宏替换遵循一定的规则。首先,宏名必须是大写的;其次,在宏体内可以使用花括号 {} 来包裹代码块;最后,宏替换只发生在预处理阶段,即在编译器真正编译源代码之前。
  6. 宏函数的对比:宏函数和普通函数在功能上有一些相似之处,但它们之间也有明显的区别。宏函数不具有函数调用的典型特征,如返回值、参数类型检查等。此外,宏函数不会被编译器优化,因此它们的执行速度可能不如普通函数快。
  7. #和##:在C语言中,# 和 ## 是两个特殊的预处理标记,用于连接字符串。# 用于连接字符串中的第一个字符,而 ## 用于连接字符串中的所有后续字符。这两个标记主要用于格式化输出,特别是在配合使用 printf 等标准库函数时。
  8. 命名约定:C语言中的变量名、函数名和结构体名等都遵循一定的命名约定。这些约定有助于提高代码的可读性和可维护性。常见的命名约定包括:使用下划线来区分单词、避免使用保留字、使用驼峰命名法等。
  9. #undef:在C语言中,使用 #undef 指令可以取消之前定义的宏。当 #undef 被用来取消某个宏的定义时,该宏在程序中不再有效,也不会被执行。
  10. 命令行定义:C语言支持从命令行界面接收输入,并将这些输入赋值给变量。这可以通过使用 getchar() 或 fgets() 等标准库函数来实现。
  11. 条件编译:C语言提供了条件编译指令,如 #if、#else 和 #endif,允许程序员根据某些条件选择性地编译代码的一部分。条件编译可以根据不同的编译环境或配置选项来调整代码的行为,从而提高代码的可移植性和适应性。
  12. 头文件的包含:在C语言中,使用 #include 指令可以将其他头文件包含到当前源文件中。这使得程序员可以重用已有的代码片段,减少重复劳动,提高代码的可复用性。
  13. 其他预处理指令:除了上述提到的预处理指令外,C语言还支持其他一些预处理指令,如 #pragma、#error 和 #warning 等。这些指令用于提供额外的编译指示或警告信息,帮助程序员理解和解决编译问题。

2. 预处理命令讲解

C语言的预处理是编译过程的一个早期阶段,它主要负责处理源代码中的预处理指令(也称为预处理命令)。这些指令以#开头,并在程序的实际编译之前由预处理器执行。以下是C语言中常见的预处理指令及其详细解释:

  1. #define

    • 这是一个宏定义指令,用于为代码中的常量或代码片段定义别名。
    • 它可以带有一个参数(称为函数式宏),也可以不带参数(称为对象式宏)。
    • 示例:
    c 复制代码
    #define PI 3.14159
    #define SQUARE(x) ((x) * (x))
  2. #undef

    • 取消之前由#define定义的宏。
    • 示例:
    c 复制代码
    #undef PI
  3. #include

    • 用于包含其他文件的内容,通常用于包含头文件(.h文件)。
    • 有两种形式:#include <filename>(用于系统头文件)和#include "filename"(用于用户定义的头文件)。
    • 示例:
    c 复制代码
    #include <stdio.h>
    #include "myheader.h"
  4. #if, #elif, #else, #endif

    • 这些指令用于条件编译。它们允许根据某些条件包含或排除代码段。
    • 可以与defined()操作符一起使用,以检查某个宏是否已定义。
    • 示例:
    c 复制代码
    #if DEBUG
        printf("Debugging information\n");
    #endif
  5. #ifdef, #ifndef

    • 这两个指令是#if defined(macro)#if !defined(macro)的简写形式。
    • 用于检查某个宏是否已定义或未定义。
    • 示例:
    c 复制代码
    #ifdef DEBUG
        // Debugging code here
    #endif
  6. #line

    • 更改__LINE____FILE__宏的输出,以反映后续的源代码行来自不同的文件或行号。
    • 通常在由其他工具(如词法分析器或语法分析器)生成的代码中看到。
    • 示例:
    c 复制代码
    #line 100 "newfile.c"
  7. #error

    • 这是一个预处理指令,用于在编译时生成错误消息。
    • 这在检查编译器版本、平台兼容性等方面很有用。
    • 示例:
    c 复制代码
    #if __STDC__ == 0
        #error "Not a standard C compiler"
    #endif
  8. #pragma

    • 这是一个特定于编译器的预处理指令,用于为编译器提供非标准的指令。
    • 不同的编译器可能对#pragma有不同的解释。
    • 示例(GCC特定):
    c 复制代码
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-variable"
    // Code that generates "unused variable" warning
    #pragma GCC diagnostic pop

预处理器执行完这些指令后,会将处理后的代码传递给编译器进行进一步的处理和编译。注意,预处理器本身不执行任何代码或进行任何计算;它只是根据预处理指令修改源代码。

结语

以上就是小编对预处理的详细讲解。

如果觉得小编讲的还可以,还请一键三连。互三必回!

持续更新中~!

相关推荐
Uu_05kkq2 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
嵌入式科普5 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
A懿轩A5 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
1 9 J6 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
仍然探索未知中7 小时前
C语言经典100例
c语言
爱吃西瓜的小菜鸡7 小时前
【C语言】矩阵乘法
c语言·学习·算法
Stark、8 小时前
【Linux】文件IO--fcntl/lseek/阻塞与非阻塞/文件偏移
linux·运维·服务器·c语言·后端
deja vu水中芭蕾9 小时前
嵌入式C面试
c语言·开发语言
stm 学习ing11 小时前
HDLBits训练3
c语言·经验分享·笔记·算法·fpga·eda·verilog hdl
CSND74015 小时前
Ubuntu vi(vim)编辑器配置一键补全main函数
linux·c语言·ubuntu·编辑器·vim