欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > C语言可变参数函数和可变参数宏

C语言可变参数函数和可变参数宏

2025/7/15 3:42:30 来源:https://blog.csdn.net/qq_23905237/article/details/142209178  浏览:    关键词:C语言可变参数函数和可变参数宏

可变参数函数

在C语言中,可变参数函数(Variable Argument Function)是一种特殊的函数形式,它可以接受不定数量的参数。这类函数允许调用者在调用时传递任意数量的参数,这对于某些场景非常有用,例如日志记录、格式化输出等。

常见的可变参数函数

C语言标准库中有一些常用的可变参数函数,包括但不限于:

  • printf:格式化输出函数,可以接受不定数量的参数。
  • fprintf:向指定流格式化输出,可以接受不定数量的参数。
  • sprintf:将格式化输出写入到字符串中,可以接受不定数量的参数。
  • snprintf:将格式化输出写入到字符串中,指定最大长度,可以接受不定数量的参数。
  • vprintf:内部使用的可变参数格式化输出函数,通常不直接调用。
  • vfprintf:内部使用的可变参数格式化输出函数,通常不直接调用。
  • vsprintf:内部使用的可变参数格式化输出函数,通常不直接调用。
  • vsnprintf:内部使用的可变参数格式化输出函数,通常不直接调用。
  • scanf:从标准输入读取格式化输入,可以接受不定数量的参数。
  • fscanf:从指定流读取格式化输入,可以接受不定数量的参数。
  • sscanf:从字符串读取格式化输入,可以接受不定数量的参数。
可变参数函数的原理

在C语言中,可变参数函数依赖于两个宏定义:va_startva_listva_argva_end。这些宏定义定义在 <stdarg.h> 头文件中。它们的工作原理如下:

  1. va_list:定义一个类型为 va_list 的变量,用于保存可变参数列表的状态。
  2. va_start:宏 va_start 初始化 va_list 变量,准备从可变参数列表的第一个参数开始处理。
  3. va_arg:宏 va_arg 获取下一个参数,并返回该参数的值。
  4. va_end:宏 va_end 清理 va_list 变量。
可变参数函数的定义

可变参数函数的定义通常包含一个固定参数列表,后面跟着一个省略号 ...。省略号表示可以有任意数量的附加参数。

#include <stdarg.h>
#include <stdio.h>// 定义一个可变参数函数
void __attribute__((format(printf,1,2))) my_printf(char *fmt,...)
{va_list args;va_start(args,fmt);vprintf(fmt,args);va_end(args);
}int main() {my_printf("Hello, %s! Today is %s.\n", "world", "Monday");return 0;
}

运行结果:

Hello, world! Today is Monday.
可变参数函数实现日志系统

实现日志分级

#include <stdio.h>
#include <stdarg.h>// 定义日志级别
typedef enum {LOG_LEVEL_DEBUG,LOG_LEVEL_INFO,LOG_LEVEL_WARNING,LOG_LEVEL_ERROR,LOG_LEVEL_NONE
} LogLevel;// 编译时指定的日志级别,可以通过宏定义在编译时设置
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_DEBUG
#endif// 日志函数
void __attribute__((format(printf,2,3))) DEBUG_PRINT(LogLevel level, const char *format, ...) {va_list args;const char *level_strings[] = {"DEBUG", "INFO", "WARNING", "ERROR"};if (level >= LOG_LEVEL) {va_start(args, format);printf("[%s] ", level_strings[level]);vprintf(format, args);printf("\n");va_end(args);}
}// 示例使用
int main() {DEBUG_PRINT(LOG_LEVEL_DEBUG, "This is a debug message.");DEBUG_PRINT(LOG_LEVEL_INFO, "This is an info message.");DEBUG_PRINT(LOG_LEVEL_WARNING, "This is a warning message. %d, %s, %.2f, %d", 2, __func__, 3.14, __LINE__);DEBUG_PRINT(LOG_LEVEL_ERROR, "This is an error message.");return 0;
}

编译:

gcc main.c -DLOG_LEVEL=LOG_LEVEL_INFO

运行结果:

[INFO] This is an info message.
[WARNING] This is a warning message. 2, main, 3.14, 36
[ERROR] This is an error message.

可变参数宏

__VA_ARGS__

#include <stdio.h>#define PRINT(...) printf(__VA_ARGS__)int main() {int a = 10;char *str = "Hello, World!";PRINT("This is a normal message.\n");PRINT("a = %d, str = %s\n", a, str);return 0;
}

利用可变参数宏改造上面利用可变参数函数实现的日志系统

#include <stdio.h>
#include <stdarg.h>// 定义日志级别
typedef enum {LOG_LEVEL_DEBUG,LOG_LEVEL_INFO,LOG_LEVEL_WARNING,LOG_LEVEL_ERROR,LOG_LEVEL_NONE
} LogLevel;// 编译时指定的日志级别,可以通过宏定义在编译时设置
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_DEBUG
#endif// 日志函数
void log_message(LogLevel level, const char *format, ...) {va_list args;const char *level_strings[] = {"DEBUG", "INFO", "WARNING", "ERROR"};if (level >= LOG_LEVEL) {va_start(args, format);printf("[%s] ", level_strings[level]);vprintf(format, args);printf("\n");va_end(args);}
}// 定义宏,用于不同的日志级别
#define LOG_DEBUG(format, ...) log_message(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...)  log_message(LOG_LEVEL_INFO, format, ##__VA_ARGS__)
#define LOG_WARNING(format, ...) log_message(LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) log_message(LOG_LEVEL_ERROR, format, ##__VA_ARGS__)// 示例使用
int main() {LOG_DEBUG("This is a debug message.");LOG_INFO("This is an info message.");LOG_WARNING("This is a warning message.");LOG_ERROR("This is an error message.");return 0;
}

编译:

gcc main.c -DLOG_LEVEL=LOG_LEVEL_INFO

运行结果:

[INFO] This is an info message.
[WARNING] This is a warning message.
[ERROR] This is an error message.

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词