C语言不定参数函数,可变参数及宏定义封装函数

以下函数包含内容:a使用宏封装可变参函数b可变参数。比较简单,无注释。
两个函数均可以打印出调用者的文件、函数、行号信息。需要参考该代码的,拿走不谢!

/* 封装调试函数*/

#define macroFunc(info)  (transparentMacroFunc(__FILE__, __func__, __LINE__, (info)))

/* 封装带可变参数的调试函数*/

#define macroFuncVargs(fmt, ...)  (transparentMacroFuncVargs(__FILE__, __func__, __LINE__, fmt, ##__VA_ARGS__))

/* file,func,line为宏封装好的入参,info为调用者传入参数*/

int transparentMacroFunc(const char *file, const char *func, int line, const char *info)
{

	printf("File:%s, Func:%s, Line:%d, info:%s\n", file, func, line, info);

	return 0;
}

/* 同上,只不过改为可变参数*/

int transparentMacroFuncVargs(const char *file, const char *func, int line, const char *fmt, ...)
{

	char buf[BUF_LEN];

	va_list args;

	memset(buf, 0, BUF_LEN);

	snprintf(buf, BUF_LEN, "File: %s, Func: %s, Line: %d info: ", file, func, line);

	/* 可变参的相关函数稍后会有解释*/

	va_start(args, fmt);

	vsnprintf(buf + strlen(buf), BUF_LEN - strlen(buf), fmt, args);

	va_end(args);

	printf("%s\n", buf);

	return 0;

}
/* 测试主函数*/

int main()

{

	macroFunc("info");

	int a = 2;

	macroFuncVargs("%d", a);

	return 0;

}

一、关于宏封装函数

宏只是一个简单的替换,所以调试代码如果遇到编译错误,就在调用出扩展开,这样能更快的定位问题。

二、关于可变参数

Linux的可变参函数在头文件stdarg.h中定义

#include <stdarg.h>

void va_start(va_list ap, last);

type va_arg(va_list ap, type);

void va_end(va_list ap);

void va_copy(va_list dest, va_list src);

Man手册中说明它们均是宏,在这里取形式上的,用函数一次来说吧。

1 在调用这几个函数之前,需要先声明一个变量,类型为va_list。

2 va_start函数初始化声明或的va,last参数为形参中最后一个类型已知的参数,目前来看也就是const char* fmt这个参数(fmt是一个形参名),是一个(格式)字符串。

va_arg函数就是用来详细解释可变参数的,遍历格式字符串,返回对应类型的值

Va_end函数与va_start函数呼应,end之后va_list的值就是未定义的了。

Va_copy函数将src复制给dest,所以dest也需要va_end函数,这个函数时C99添加的,添加原因与不同的系统实现有关,man手册中有例子,可以查看。

注:这些宏与旧版的varargs.h中的不兼容

3 如果想要直接打印或者使用这些可变参,stdargs提供了几个专用的函数,直接使用printf之类的会出现意想不到的错误哦。

看看最后两个参数的类型,果然是量身定做吧。

一般在调试打印Debug信息的时候,需要可变参数的宏.从C99开始可以使编译器标准支持可变参数宏(variadic macros),另外GCC也支持可变参数宏,但是两种在细节上可能存在区别.

(1). VA_ARGS

VA_ARGS 将"…"传递给宏.如

#define debug(format, …) fprintf(stderr, format, VA_ARGS)

(2). GCC的复杂宏

GCC使用一种不同的语法,从而可以给可变参数一个名字,如同其它参数一样.

#define debug(format, args…) fprintf (stderr, format, args)

这和第一条的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述.

(3). ##VA_ARGS

上面两个定义的宏,如果出现debug(“A Message”)的时候,由于宏展开后有个多余的逗号,所以将导致编译错误.

为了解决这个问题,CPP使用一个特殊的"##"操作,格式如下:

#define debug(format, …) fprintf (stderr, format, ## VA_ARGS)

这里,如果可变参数被忽略或为空,"##"操作将使预处理器(preprocessor)去除掉它前面的那个逗号.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言中,我们可以使用标准库中的 `<stdarg.h>` 头文件来定义可变参数函数。下面是一个示例代码: ```c #include <stdio.h> #include <stdarg.h> void printNumbers(int count, ...) { va_list args; // 声明一个va_list类型的变量 va_start(args, count); // 初始化va_list变量 for (int i = 0; i < count; i++) { int num = va_arg(args, int); // 从可变参数列表中获取参数 printf("%d ", num); } va_end(args); // 结束可变参数的获取 printf("\n"); } int main() { printNumbers(5, 1, 2, 3, 4, 5); // 调用可变参数函数 return 0; } ``` 在上述示例代码中,我们首先包含了 `<stdarg.h>` 头文件,然后定义了一个名为 `printNumbers` 的可变参数函数函数的第一个参数 `count` 用于指定可变参数的数量。然后使用 `va_list` 声明了一个可变参数列表的变量 `args`。通过调用 `va_start` 宏,我们对 `args` 进行了初始化,该宏接受两个参数,第一个是 `args`,第二个是最后一个固定参数的前一个参数(即 `count`)。接下来,我们使用 `va_arg` 宏在循环中逐个获取可变参数的值,第一个参数是 `args`,第二个参数是要获取的参数的类型。最后,我们使用 `va_end` 宏结束可变参数的获取。 在 `main` 函数中,我们调用了 `printNumbers` 函数来测试可变参数的使用。 需要注意的是,在C语言中,可变参数函数的实现是比较底层和繁琐的,需要开发者手动管理参数列表的获取和结束。因此,在实际开发中,如果可能的话,建议使用C++中提供的更加方便和安全的可变参数函数实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程子的小段

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值