C语言中的宏



C语言中的宏是在编译预处理器之前,为特定常量值或代码语句指定的名称,并将其替换为其值/代码。C宏使用#define预处理器指令定义。

可用于代码重用、定义常量值、定义内联函数和条件编译。

本教程将介绍以下不同类型的C宏:

  • 类对象宏
  • 类函数宏
  • 链式宏
  • 可变参数宏
  • 预定义宏

类对象宏

定义常量的宏称为类对象宏。

语法

使用以下语法:

#define name value

类对象宏示例

在以下示例中,我们定义了一个类对象宏:

#include <stdio.h>

// Defining macros
#define PI 3.14
#define MAX 10

int main() {
   // Printing the values
   printf("Value of PI = %d\n", PI);
   printf("Value of MAX = %d\n", MAX);

   return 0;
}

类函数宏

要定义类函数宏,您使用相同的“#define”指令,但在宏名称后立即添加一对括号,其中包含一个或多个参数。此类宏仅在其名称后出现一对括号时才展开。

当预处理器扩展此类宏时,它会将指定的参数合并到替换文本中。类函数宏通常称为带参数(或自变量)的宏。

语法

类函数宏定义如下:

#define macro_name([parameter_list]) replacement_text

类函数宏示例

类函数宏的示例如下:

#include <stdio.h>

#define square(x) ((x) * (x))

int main(){

   int x = 5;
   printf("x: %d \tSquare of x: %d", x, square(x));
   return 0;
}

输出

运行此代码时,将产生以下输出:

x: 5 	Square of x: 25

定义类函数宏的规则

定义函数的一些规则也适用于宏:

  • 宏可以不带参数定义
  • 宏可以带固定数量的参数定义
  • 宏可以带可变数量的参数定义

例如,当您使用此类宏时,逗号分隔的参数列表必须包含与宏定义中的参数一样多的参数。

不带参数的类函数宏

类函数宏也可以不带参数定义。

示例1

以下示例演示了如何使用不带参数的宏:

#include <stdio.h>

#define MESSAGE() printf("Hello World");

int main() {

   int x = 5;
   MESSAGE();
   return 0;
}

输出

运行代码并检查其输出:

Hello World

一些标准库也在其中提供了宏定义。例如,getchar()宏展开后,实现getc()函数如下:

#define getchar() getc(stdin)

同样,putchar()宏封装了putc()函数:

#define putchar(x) putc(x, stdout)

示例2

以下程序定义了一个名为LOOP(x)的宏,并根据其参数运行一个**for**循环:

#include <stdio.h>

#define LOOP(x) {\
   for (int i = 1; i <= x; i++)\
   printf("Iteration no: %d\n", i);\
}

int main() {

   int x = 3;
   LOOP(x);
}

输出

运行此代码时,将产生以下输出:

Iteration no: 1
Iteration no: 2
Iteration no: 3

链式宏

当一个宏嵌套在另一个宏中时,它们被称为链式宏。

链式宏示例

以下示例演示了如何使用链式宏:

#include <stdio.h>

#define PI 3.142
#define CIRCUMFERENCE(x) (2*PI*x)

int main(){

   int x = 5;
   printf("Circumference of a circle with radius %d is %f", x, CIRCUMFERENCE(x));
   return 0;
}

输出

运行此代码时,将产生以下输出:

Circumference of a circle with radius 5 is 31.420000

可变参数宏

您还可以定义带可变数量参数的宏或可变参数宏。带可变长度参数的宏是一项功能,使宏能够接受任意数量的参数。您可以将位置参数和关键字参数传递给宏。

定义可变参数宏时,省略号(…)作为参数传递以捕获可变数量的参数。要使用可变参数宏,省略号可以指定为宏定义中的最后一个形式参数。此标记序列将替换宏体中出现的标识符__VA_ARGS__。

__VA_ARGS__将被与省略号匹配的所有参数替换,包括它们之间的逗号。请注意,可变参数宏只能在C99兼容的C编译器及更高版本中使用。

可变参数宏示例

请查看以下示例:

#include <stdio.h>

#define MAX_ARGS 5		// Define maximum number of allowed arguments
#define ARGS(x, ...) do {\
   printf("%d\n", ##__VA_ARGS__); \
} while (0)

int main() {

   ARGS(1, 2, 3); 		// 3 arguments
   ARGS(1, 2, 3, 4, 5, 6);	// 6 arguments 
   return 0;
}

输出

运行代码并检查其输出:

2
2

预定义宏

ANSI C定义了许多宏。尽管每个宏都可用于编程,但不应直接修改预定义宏。

描述
__DATE__ 当前日期,以“MMM DD YYYY”格式的字符文字表示。
__TIME__ 当前时间,以“HH:MM:SS”格式的字符文字表示。
__FILE__ 包含当前文件名,以字符串文字表示。
__LINE__ 包含当前行号,以十进制常量表示。
__STDC__ 当编译器符合ANSI标准时定义为1。

示例

以下示例演示了如何在C程序中使用预定义宏:

#include <stdio.h>

int main() {

   printf("File :%s\n", __FILE__ );
   printf("Date :%s\n", __DATE__ );
   printf("Time :%s\n", __TIME__ );
   printf("Line :%d\n", __LINE__ );
   printf("ANSI :%d\n", __STDC__ );
}

输出

运行此代码时,将产生以下输出:

File: main.c
Date: Mar 6 2024
Time: 20:12:19
Line: 8
ANSI: 1
广告