#define NAME VALUE
我知道无论何时编译器看到这个,它都会用 VALUE 替换 NAME。但是我对预处理指令的工作感到困惑,例如:
#define CONFIG_VAR(name, type, value)
这不会告诉编译器替换任何东西,但我可以看到类似的语句
CONFIG_VAR(rank, int, 100)
这将成功编译。这是如何运作的 ?
#define NAME VALUE
我知道无论何时编译器看到这个,它都会用 VALUE 替换 NAME。但是我对预处理指令的工作感到困惑,例如:
#define CONFIG_VAR(name, type, value)
这不会告诉编译器替换任何东西,但我可以看到类似的语句
CONFIG_VAR(rank, int, 100)
这将成功编译。这是如何运作的 ?
在您的示例中,这根本不会做任何事情。任何参数,即使是那些看起来应该给出编译错误的参数,都被接受,并且整个宏调用被替换为空字符串。
但是,如果您稍后将定义替换为以下内容:
#define CONFIG_VAR(name, type, value) add_config_var<type>(name, value)
它会突然做一些有用的事情。所以,我猜这个宏是一个占位符,用于表示在程序的那一部分中尚未(尚未)实现或不可用的功能。
当你说:
#define FOO BAR
预处理器所做的是每次在此之后用文本替换它看到的文本, 一个宏定义。该过程称为宏扩展。这主要用于定义常量,例如:FOO
BAR
#define N 128
#define MASK (~(1 << 4))
它可以(ab)用来做一些非常时髦的事情,因为它对表达式、语句或任何东西一无所知。所以:
#define CONST (1 + 3 << (x))
实际上是可以的,并且会使用 each time 的当前值扩展到每次看到(1 + 3 << (x))
它。也像:x
#define START 5 * (1 +
#define END + 5)
其次是START 2 + 3 + 4 END
可以预见地给出5 * (1 + 2 + 3 + 4 +
5)`
还可以选择使用参数定义宏,例如:
#define BAD_SQUARE(x) x * x
其中,如果调用 asBAD_SQUARE(a)
将扩展为a * a
. 但BAD_SQUARE(a + b)
扩展为a + b * a + b
,这不是预期的(大概......)。
这来自 C 的黑暗时代,今天的 C/C++ 具有更安全/更清洁的机制来获得相同的结果(const
在 C++ 中使用,在 C 中它遗憾地定义了一个变量,而不是一个真正的常量;在 C/C++ 或模板中使用内联函数在 C++ 中)。有太多的代码使用这种预处理器(以及太多的手指使用这种方式),所以实际上不可能摆脱它。根据经验,学习使用宏阅读代码,同时学习不使用宏编写代码(在合理的情况下,有时它们会派上用场......)。
这是一个宏(在 C 中比在 C++ 中更常见)。根据您提供的定义,预处理器将删除该“功能”的出现。一个常见的用例通常用于日志记录:
#ifdef DEBUG
#define dprintf(...) printf(...)
#else
#define dprintf(...) // This will remove dprintf lines
#endif
在 C++ 中,我相信一般惯例是使用内联函数,因为它们在性能方面提供相同的值,但也经过类型检查。
在这种情况下,预处理器只是删除这些字符串(替换为空)。广泛使用的技术。
这是重要的示例(实际上只是一种可能的用法):
#if DEBUG_ON
#define LOG(level, string) SomeLogger(level, string)
#else
#define LOG(level, string)
#endif
可能您应该更熟悉C 预处理器。
有一种比较接近的技术(X 宏)可以构建代码来处理基于定义的操作的重复列表。
如果这确实是整个宏定义,那么它只是将这个类似函数的宏定义为扩展为空(一个空字符串)。例如,在源代码中,
CONFIG_VAR(rank, int, 100);
将转化为
;