Cprogramming 简明教程

Macros in C

Macros in C 是给予特定常数值或代码语句的名称,它们在编译前处理器之前用它们的值/代码替换。 C Macros 使用 #define 预处理程序指令来定义。

Macros 对于代码重用、定义常量、定义内联函数和条件编译很有用。

以下是本教程中我们将涵盖的不同类型的 C 宏 –

  1. Object-like Macros

  2. Function-like Macros

  3. Chained Macros

  4. Variadic Macros

  5. Predefined Macros

Object-like Macros

定义常量的宏是类对象宏。

Syntax

它使用以下语法完成 −

#define name value

Example of Object-like Macros

在下面的示例中,我们正在定义一个类对象宏 −

#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;
}

Function-like Macro

要定义一个类函数宏,您使用相同的“#define”指令,但在宏名称后面立即使用一对括号,并带有一个或多个参数。这种宏仅当它的名称后面出现一对括号时才展开。

当预处理器扩展这种宏时,它将替换文本中的指定参数相结合。类似函数的宏经常被称作带参数(或变量)的宏。

Syntax

类似函数的宏被定义如下 −

#define macro_name([parameter_list]) replacement_text

Example of Function-like Macros

下面是类似函数的宏的一个例子 −

#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

Rules for Defining Function-like Macros

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

  1. 宏可以在没有参数的情况下定义

  2. 宏可以在有固定数量参数的情况下定义

  3. 宏可以在有数量不确定的情况下定义

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

Function-like Macros without Arguments

类似函数的宏也可以在没有参数的情况下定义。

Example 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)

Example 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

Chained Macros

当我们有一个宏嵌套在另一个宏内部时,它们被称为链接宏。

Example of Chained Macros

下面的例子展示了你如何使用链接宏 −

#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

Variadic Macros

您还可以使用数量不确定的参数或可变参数的宏来定义一个宏。具有可变长度参数的宏是一种使宏能够接受任何数量参数的功能。您可以将位置参数以及关键字参数传递给一个宏。

在定义可变参数宏时,省略号(…)作为参数给出以获取数量不确定的参数。为了使用可变参数宏,省略号可以被指定为宏定义中的最后一个形式参数。令牌的这个序列将替换宏体中标识符 VA_ARGS 无论它出现在哪里。

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

Example of Variadic Macros

请看以下示例:

#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

Predefined Macros

ANSI C 定义了许多宏。虽然每个宏都可用在编程中,但是预定义的宏不应该直接被修改。

Macro

Description

DATE

当前日期,字符文本格式为“MMM DD YYYY”。

TIME

当前时间,字符文本格式为“HH:MM:SS”。

FILE

此项包含当前文件名,字符串文本格式。

LINE

此项包含当前行号,十进制常量。

STDC

如果编译器符合 ANSI 标准,则定义为 1。

Example

以下示例演示如何在 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