- C编程教程
- C - 首页
- C语言基础
- C - 概述
- C - 特性
- C - 历史
- C - 环境设置
- C - 程序结构
- C - Hello World
- C - 编译过程
- C - 注释
- C - 词法单元
- C - 关键字
- C - 标识符
- C - 用户输入
- C - 基本语法
- C - 数据类型
- C - 变量
- C - 整数提升
- C - 类型转换
- C - 类型强制转换
- C - 布尔值
- C语言中的常量和字面量
- C - 常量
- C - 字面量
- C - 转义序列
- C - 格式说明符
- C语言中的运算符
- C - 运算符
- C - 算术运算符
- C - 关系运算符
- C - 逻辑运算符
- C - 位运算符
- C - 赋值运算符
- C - 一元运算符
- C - 自增和自减运算符
- C - 三元运算符
- C - sizeof运算符
- C - 运算符优先级
- C - 其他运算符
- C语言中的决策
- C - 决策
- C - if语句
- C - if...else语句
- C - 嵌套if语句
- C - switch语句
- C - 嵌套switch语句
- C语言中的循环
- C - 循环
- C - while循环
- C - for循环
- C - do...while循环
- C - 嵌套循环
- C - 无限循环
- C - break语句
- C - continue语句
- C - goto语句
- C语言中的函数
- C - 函数
- C - 主函数
- C - 按值调用函数
- C - 按引用调用函数
- C - 嵌套函数
- C - 可变参数函数
- C - 用户自定义函数
- C - 回调函数
- C - 返回语句
- C - 递归
- C语言中的作用域规则
- C - 作用域规则
- C - 静态变量
- C - 全局变量
- C语言中的数组
- C - 数组
- C - 数组的特性
- C - 多维数组
- C - 将数组传递给函数
- C - 从函数返回数组
- C - 可变长数组
- C语言中的指针
- C - 指针
- C - 指针和数组
- C - 指针的应用
- C - 指针运算
- C - 指针数组
- C - 指针到指针
- C - 将指针传递给函数
- C - 从函数返回指针
- C - 函数指针
- C - 指向数组的指针
- C - 指向结构体的指针
- C - 指针链
- C - 指针与数组
- C - 字符指针和函数
- C - 空指针
- C - void指针
- C - 野指针
- C - 解引用指针
- C - 近、远和巨大指针
- C - 指针数组的初始化
- C - 指针与多维数组
- C语言中的字符串
- C - 字符串
- C - 字符串数组
- C - 特殊字符
- C语言中的结构体和联合体
- C - 结构体
- C - 结构体和函数
- C - 结构体数组
- C - 自引用结构体
- C - 查找表
- C - 点(.)运算符
- C - 枚举(或枚举类型)
- C - 结构体填充和打包
- C - 嵌套结构体
- C - 匿名结构体和联合体
- C - 联合体
- C - 位域
- C - typedef
- C语言中的文件处理
- C - 输入和输出
- C - 文件I/O(文件处理)
- C预处理器
- C - 预处理器
- C - 指令
- C - 预处理器运算符
- C - 宏
- C - 头文件
- C语言中的内存管理
- C - 内存管理
- C - 内存地址
- C - 存储类别
- 其他主题
- C - 错误处理
- C - 可变参数
- C - 命令执行
- C - 数学函数
- C - static关键字
- C - 随机数生成
- C - 命令行参数
- C编程资源
- C - 问答
- C - 快速指南
- C - 速查表
- C - 有用资源
- C - 讨论
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