#if / #elif / #else 用于在预处理器阶段实现简单的逻辑。在此示例中,它们用于根据是否定义了其他一些值来正确设置 TABLE_SIZE 的值。
我们为什么需要这个?
一些值依赖于其他一些值,如本例所示。这些其他值可能根本没有定义——这就是为什么我们也需要考虑到这一点。因为TABLE_SIZE、ARRAY_SIZE等都是defined,编译时改了,不修改代码。这是使用defines 而不是常规变量的优势之一。使用gcc时,可以这样设置defines:
gcc -o test test.c -DBUFFER_SIZE=128
此示例将BUFFER_SIZE 的值设置为128(除非它再次在源代码中重新定义)。
此外,它还可用于创建可移植代码,其中一些选项(甚至部分代码)因各种操作系统或架构而异。
预处理器指令应该放在哪里?
通常,它们被放置在头文件中。这种方式更容易管理它们 - 您在所有文件中设置了相同的宏,其中包括特定的标题。无论如何,这只是一个约定。从技术上讲,预处理器指令可以放置在代码中的任何位置(但在使用它们之前),无论是在头文件中还是在源文件中。
宏的作用域是什么?
Proprocessor 仅执行简单的文本替换(以及一些更复杂事物的宏扩展,例如可变长度参数)。宏可以在定义后使用,直到未定义为止。考虑这个例子:
/* Here, TEST is not defined. */
#define TEST 123
/* TEST is defined here, and can be used. */
#undef TEST
/* TEST is undefined again, and cannot be used. */
编译库或应用程序时,可以创建多个翻译单元。其中这些作为源文件,处理了所有#include 指令。考虑这个例子:
在header1.h:
#define TEST 123
在header2.h:
#undef TEST
#define ABC 456
在test.c:
#include "header1.h" /* Defines TEST */
void test1() {
printf("%d", TEST); /* OK, TEST has been defined in `header1.h`, which is included above. */
}
#include "header2.h" /* Undefines TEST, defines ABC */
void test2() {
printf("%d", ABC); /* OK, ABC has been defined in `header2.h`, which is included above. */
/* printf("%d", TEST); */ /* Can't do that - TEST has been undefined! */
}
有时检查预处理器的功能可能很有用。对于gcc,那就是:
gcc -E test.c -o test.preprocessed