4.11 c 预处理器

The C Preprocessor 预处理器这一节涉及内容太多,本文只作为入门。

4.11.1 一些概念解释

在 c 语言较早的时期,预处理器是一个单独的程序,它的输出提供给编译器,如今,预处理器通常和编译器集成在一起,而且输出也不一定全是 c 代码。

下面看一个例子:

4.11.1-macro-define-view.c
#include <stdio.h>

#define PI 3.14159
#define SQUARE(x) ((x) * (x))

int main() {
    double radius = 2.0;
    double area;

    // 宏调用
    area = PI * SQUARE(radius);
    
    printf("圆的面积为:%f\n", area);

    return 0;
}
gcc -E 4.11.1-macro-define-view.c -o 4.11.1-macro-define-view-output_preprocessed_file.c
4.11.1-macro-define-view-output_preprocessed_file.c
...
    
# 410 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h" 2 3 4
# 2 "4.11.1-macro-define-view.c" 2




int main() {
    double radius = 2.0;
    double area;


    area = 3.14159 * ((radius) * (radius));

    printf("圆的面积为:%f\n", area);

    return 0;
}

编译前

预处理器是一个小软件,它可以在编译前处理 c 程序。c 语言和 c++语言因为依赖于预处理器而不同于其他的编程语言。 《c 语言程序设计现代方法第 2 版》p225

预处理器的行为是由预处理指令控制的。 #

#define 定义了一个宏,把宏看成用来代表其他东西的一个名字,例如常量。

宏调用指的是在源代码中使用宏名称来引用宏定义的过程。当预处理器遇到宏调用时,它会根据宏定义将宏调用替换为对应的宏定义文本。

宏展开是指预处理器在遇到宏调用时将宏名称替换为宏定义文本的过程。它是预处理器处理源代码的一个重要步骤,预处理器在预处理阶段会扫描源代码中的宏调用,并将其展开为宏定义中指定的文本,然后再将展开后的代码传递给编译器进行后续处理。

https://gcc.gnu.org/onlinedocs/cpp/Macros.html

A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.

宏是已指定名称的代码片段。每当使用该名称时,它就会被宏的内容替换。宏有两种。它们的主要区别在于使用时的外观。类对象宏类似于数据对象使用时,类函数宏类似于函数调用。

4.11.2 #include 文件包含

4.11.3 #define 宏替换

4.11.4 Object-like macros

对象式宏,或者称为简单的宏,用来定义一些常量( manifest constant),给数值、字符值、字符串值命名。

这里提到 magic number 这在 1.4 节符号常量有提,可以减少 magic number 的干扰。

https://gcc.gnu.org/onlinedocs/cpp/Object-like-Macros.html

An object-like macro is a simple identifier which will be replaced by a code fragment. It is called object-like because it looks like a data object in code that uses it. They are most commonly used to give symbolic names to numeric constants.

类似对象的宏是一个简单的标识符,它将被代码片段替换。它被称为类对象,因为它在使用它的代码中看起来像数据对象。它们最常用于为数字常量提供符号名称。关闭

You create macros with the ‘#define’ directive. ‘#define’ is followed by the name of the macro and then the token sequence it should be an abbreviation for, which is variously referred to as the macro’s body, expansion or replacement list.

您可以使用“#define”指令创建宏。 '#define' 后跟宏的名称,然后是它应该 缩写的标记序列,它被不同地称为宏的 主体、扩展或替换列表。

#define BUFFER_SIZE 1024

4.11.5 function-like macros

函数式宏,或者叫带有参数的宏,

4.11.5 func-macro.c
#include <stdio.h>

// 带有参数的宏定义
#define MAX(x, y) ((x) > (y) ? (x) : (y))

int main() {
    int a = 5;
    int b = 10;
    
    // 调用带有参数的宏
    int max_value = MAX(a, b);
    
    printf("较大的数是:%d\n", max_value);

    return 0;
}
condition-express-intro
(condition) ? (value_if_true) : (value_if_false)

((x) > (y) ? (x) : (y))

4.11.6 Predefined Macros

https://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html

Several object-like macros are predefined; you use them without supplying their definitions. They fall into three classes: standard, common, and system-specific.

预定义了几个类似对象的宏;您使用它们时无需提供它们的定义。它们分为三类:标准、通用和系统特定。

https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html

__DATE__ 介绍一个用于在编译时插入当前的日期字符串的 标准预定义宏(Standard-Predefined-Macros),这个特性通常用于程序的版本信息、日志记录等场景中。

4.11.6 Standard-Predefined-Macros.c
#include <stdio.h>

int main() {
    printf("当前的日期是:%s\n", __DATE__);
    return 0;
}

/* 
  ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ OUTPUT:                                                                                                         │
  │                                                                                                                 │
  │ 当前的日期是:Jan 30 2024                                                                                              │
  └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
 */

Last updated