在本教程中,您将通过简单的示例学习 C 语言中的预处理器指令,如 #include、#define、#if 等。
C 语言中的预处理器指令,通常用术语“CPP”表示,以三种不同的方式工作。它用作
在 C 语言中,我们必须先编译程序才能运行。预处理器是一种特殊类型的程序,它在程序被编译器处理之前处理程序的某些部分。这可以形象地表示如下

井号(#)表示预处理器包含。虽然我们可以在程序的任何部分使用它,但通常的做法是在程序开头就定义它。
C 语言的主要预处理器指令根据功能分为四组。

显然,您已经注意到,几乎没有哪个程序不使用 #include 预处理器。几乎每个程序都以这样的方式开始
#include <stdio.h>
main()
{
}
这意味着写在头文件 stdio.h 中的所有内置函数都可以在程序内部使用。同样,根据程序的性质,我们可以在程序中包含标准头文件和用户自定义的头文件。
如本教程前面所讨论的,宏是可以被一个值替换的代码段。我们可以使用 #define 指令创建宏。语法是
#define token value
在这里,预处理器的工作是在程序中的每个场合用指定的字符替换标识符。宏分为两种类型
类对象宏
通常用一个值替换标识符的宏被归类为类对象宏。最常用于表示数字常量。这里有一个例子
#define LIMIT 10
这里,LIMIT 是宏名称,它替换了值 10。请观察下面的例子,它说明了类对象宏的工作原理。
#include<stdio.h>
#define LIMIT 10
int main()
{
for(int i=1;i<=LIMIT;i++)
{
printf("%d\t",i);
}
return 0;
}
在这里,编译器会将 'LIMIT' 读作 10 并相应地处理程序,从而得到以下输出
1 2 3 4 5 6 7 8 9 10
类函数宏或参数化宏
参数化形式极大地增强了宏的能力,尤其是在执行数学计算方面。它使宏能够像基于变量的函数一样工作。假设我们想确定一个数的立方。为此,我们通常需要创建一个像这样的函数
int cube(int a)
{
return a*a*a;
}
使用参数化宏,我们可以在一行中完成相同的操作。
#define cube(a) ((a) * (a) *(a))
这是示例
#include<stdio.h>
#define CUBE(a) ((a)*(a)*(a))
int main()
{
printf("%d",CUBE(10));
return 0;
}
输出
1000
我们必须记住,在程序中使用宏之前,我们必须使用 #define 指令来定义它们。
C 中的 undef 指令用于取消定义一个宏,明确地说就是取消已经定义的宏。语法是
#undef token
以下程序演示了 #undef 指令的工作原理。
#include<stdio.h>
#define CUBE(a) ((a)*(a)*(a))
#define LIMIT 20
#undef LIMIT
int main()
{
printf("%d",CUBE(LIMIT));
return 0;
}
在上面的代码片段中,我们取消了宏 LIMIT 的定义,因此当我们调用该函数时,输出显然会是一个错误,如下所示
error: 'LIMIT' undeclared (first use in this function)|
C 编程中的条件指令用于检查程序中是否已经定义了某个宏,并指示预处理器是包含还是丢弃这组代码。我们可以借助指令 #ifdef、#ifndef、#if、#else、#elif、#endif 来实现条件编译。现在让我们逐一了解它们。
#ifdef 预处理器指令检查是否存在由 #define 定义的宏,如果条件满足,则允许编译一段代码。否则,这部分代码将不会被编译。#ifdef 的原型如下
#ifdef MACRO
//Set of codes
#endif
该指令检查宏是否不存在,并执行放置在 ifndef 和 endif 之间的代码集。语法如下
#ifndef MACRO
//Set of codes
#endif
现在让我们观察一下如何在程序中实现 #ifdef 和 ifndef。
#include<stdio.h>
#define CUBE(a) ((a)*(a)*(a))
#define LIMIT 20
int main()
{
#ifdef LIMIT
printf("Given limit is %d",LIMIT);
#endif // LIMIT
#ifndef CUBE
printf("Cube %d :",CUBE(3));
#endif // CUBE
return 0;
}
输出
Given limit is 20
所有这些指令仅在满足指定条件或表达式时才执行代码。
#if 的语法如下
#if macro_expression
//Set of codes
#endif
#else 的语法
#if macro_expression
//Set of codes for if part
#else
// set of codes for else part
#endif
#elif 的语法
#if macro_expression
//Set of codes for if part
#elif
// set of codes for elif part
#else
//set of codes for else part
#endif
#include<stdio.h>
#include<conio.h>
#define AGE
int main()
{
#if AGE >=18
printf("YOU ARE ELIGIBLE FOR VOTING");
#else
printf("YOU ARE NOT ELIGIBLE FOR VOTING");
#endif
}
有不同类型的预处理器运算符。现在,我们将讨论最常用的几种。它们是
通常,像 #define 这样的宏会一直工作到遇到新行为止。有时我们需要宏足够大以容纳所有字符,而将所有这些写在单行中会影响程序的可读性。续行运算符('\')告诉编译器将下一行视为前一行的部分。这里有一个例子:
//Continuation Operator in C
#include<stdio.h>
# define CUBE(a) \
printf("Cube of %d is %d\n",a,((a)*(a)*(a)));
int main()
{
CUBE(6);
return 0;
}
输出
Cube of 6 is 216
字符串化运算符是预处理器运算符之一,用于操作字符串。顾名思义,宏的字符串化运算符能够将参数转换为字符串常量。此运算符仅适用于带参数的宏。
#define Macro_name(arg) #arg
考虑以下示例
#include <stdio.h>
#define display(text) #text
int main(void)
{
printf(display(WELCOME TO LEARN E TUTORIALS));
return 0;
}
输出
WELCOME TO LEARN E TUTORIALS
解释:在这段代码中,我们向 printf() 函数传递了一个宏。由于宏在程序编译前被处理,预处理器会将 display(WELCOME TO LEARN E TUTORIALS) 展开为 "WELCOME TO LEARN E TUTORIALS"。然后我们的 printf() 函数就变成了 printf("WELCOME TO LEARN E TUTORIALS"),因此得到了这个输出。
标记粘贴运算符是一种预处理器运算符,用于将宏内部作为参数给出的两个独立的标记粘合在一起。符号 '##' 充当连接器,通过组合其两侧的标记。## 运算符可用于以下标记
1. 标识符,如变量名、函数名等。 2. 关键字和变量名,如 int、while、volatile 等。 3. 数据类型,如字符串、数字、字符、true 或 false。 4. 数学运算符和标点符号,如 (,=,); 等。
语法
#define Macro_name(arg1,arg2,...,argN) arg1##arg2##...##argN
检查以下程序
#include <stdio.h>
#define join(x, y) x##y
int main()
{
printf("join(20, 30) = %d\n", join(20, 30));
return 0;
}
输出
join(20, 30) = 2030
该运算符的工作是检查标识符是否已由 #define 定义。它有两个二进制输出:true 和 false。如果标识符存在,它返回 1。否则,它将标记为 '0'。这里是一个描述 #defined 应用的例子。
// defined operator
#include <stdio.h>
#if !defined (FUNCTION)
#define FUNCTION "Hello World!!"
#endif
int main(void)
{
printf("\n\t %s ", FUNCTION);
return 0;
}
输出
Hello World!!
在这里,#defined 会查找 'FUNCTION' 宏。如果未找到,则会创建一个新的。之后,在 main 函数下,编译器会将 "FUNCTION" 这个词读作 "Hello World!"。
探索更多
#line 指令
#pragma 指令
#error 指令