Cprogramming 简明教程
Preprocessors in C
C 预处理器不是编译器的一部分,而是编译过程中的一个单独步骤。简单来说,C 预处理器只是一个文本替换工具,它指示编译器在实际编译之前执行所需的预处理。我们称 C 预处理器为 CPP。
在 C 编程中, preprocessing 是 C 代码编译的第一步。它发生在 tokenization 步骤之前。预处理器的主要功能之一是包含 header files ,其中包含程序中使用的库函数。C 中的预处理器还定义常量和扩展宏。
C 中的预处理器语句称为 directives 。程序的预处理器部分始终出现在 C 代码的顶部。每个预处理器语句都以哈希 (#) 符号开头。
Preprocessor Directives in C
下表列出了所有重要的预处理程序指令:
Directive |
Description |
# define |
Substitutes a preprocessor macro. |
#include |
从另一个文件中插入一个特定头。 |
#undef |
Undefines a preprocessor macro. |
#ifdef |
如果定义了此宏,则返回 true。 |
#ifndef |
如果未定义此宏,则返回 true。 |
#if |
测试编译时条件是否为真。 |
#else |
The alternative for #if. |
#elif |
在一个语句中使用 #else 和 #if。 |
#endif |
Ends preprocessor conditional. |
#error |
在 stderr 上打印错误消息。 |
#pragma |
使用标准化方法向编译器发出特殊命令。 |
Preprocessors Examples
分析以下示例以了解各种指令。
此 #define 指令告诉 CPP 将 MAX_ARRAY_LENGTH 的实例替换为 20。使用 #define 以增加常量的可读性。
#define MAX_ARRAY_LENGTH 20
以下指令告诉 CPP 从系统库中获取“stdio.h”并将文本添加到当前源文件中。下一行告诉 CPP 从本地目录获取“myheader.h”并将内容添加到当前源文件中。
#include <stdio.h>
#include "myheader.h"
现在,来看一下以下 #define 和 #undef 指令。它们告诉 CPP 取消定义现有的 FILE_SIZE 并将其定义为 42。
#undef FILE_SIZE
#define FILE_SIZE 42
以下指令告诉 CPP 仅在 MESSAGE 尚未定义时定义 MESSAGE。
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
以下指令告诉 CPP 处理在 DEBUG 定义时括起来的语句。
#ifdef DEBUG
/* Your debugging statements here */
#endif
如果在编译时将 -DDEBUG 标志传递给 gcc 编译器,这很有用。这将定义 DEBUG,以便您可以在编译期间随时打开和关闭调试。
Predefined Macros in C
ANSI C 定义了许多宏。虽然每个宏都可用在编程中,但是预定义的宏不应该直接被修改。
Macro |
Description |
DATE |
当前日期,字符文本格式为“MMM DD YYYY”。 |
TIME |
当前时间,字符文本格式为“HH:MM:SS”。 |
FILE |
此项包含当前文件名,字符串文本格式。 |
LINE |
此项包含当前行号,十进制常量。 |
STDC |
如果编译器符合 ANSI 标准,则定义为 1。 |
Preprocessor Operators
C 预处理器提供以下运算符来帮助创建宏:
Example: The Macro Continuation (\) Operator in C
宏通常限制在一行中。宏延续运算符 (\) 用于继续一行中过长的宏。请看以下示例:
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main() {
message_for(Ram, Raju);
}
当你运行这段代码时,它将产生以下输出:
Ram and Raju: We love you!
Example: The Stringize (
字符串化运算符(#),也称为井号运算符,在宏定义中使用时,会将宏参数转换为字符串常量。
字符串化运算符只能在具有指定参数或参数列表的宏中使用。例如:
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main() {
message_for(Carole, Debra);
return 0;
}
运行代码并检查其输出:
Carole and Debra: We love you!
Example: The Token Pasting (
宏定义中的标记粘贴运算符 (##)将两个参数组合起来。它允许多个宏定义中的标记加入到单独的标记中。例如:
#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main() {
int token34 = 40;
tokenpaster(34);
return 0;
}
当你运行这段代码时,它将产生以下输出:
token34 = 40
Example: The defined() Operator in C
预处理器定义的运算符用于常量表达式中,以确定标识符是否使用 #define 定义。如果指定了标识符,则值为 true(非零)。如果未定义符号,则值为 false(零)。
以下示例显示如何在 C 程序中使用 defined operator :
#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main() {
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
运行代码并检查其输出:
Here is the message: You wish!