【发布时间】:2018-02-24 23:54:33
【问题描述】:
我已经查看了一些在 C 中执行此操作的方法,但我只找到了 C99。
但我遇到了以下解决方案,取自Lock Less。
问题是,我不太了解它是如何工作的,我想知道那里发生的事情的基本原理以便能够更清楚地理解它。
我在网上搜索了一段时间,发现 this 关于 __VA_ARGS__,但不幸的是,仅此还不够。
我非常感谢您对此问题的解释或一些指导,任何类型的参考都会有所帮助。
我已经使用带有 -ansi 标志的 GCC-5.4.1 编译了这段代码。
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#define COUNT_PARMS2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
#define COUNT_PARMS(...)\
COUNT_PARMS2(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
void count_overload1(int p1)
{
printf("One param: %d\n", p1);
}
void count_overload2(double *p1, const char *p2)
{
printf("Two params: %p (%f) %s\n", p1, *p1, p2);
}
void count_overload3(int p1, int p2, int p3)
{
printf("Three params: %c %d %d\n", p1, p2, p3);
}
void count_overload_aux(int count, ...)
{
va_list v;
va_start(v, count);
switch(count)
{
case 1:
{
int p1 = va_arg(v, int);
count_overload1(p1);
break;
}
case 2:
{
double *p1 = va_arg(v, double *);
const char *p2 = va_arg(v, const char *);
count_overload2(p1, p2);
break;
}
case 3:
{
int p1 = va_arg(v, int);
int p2 = va_arg(v, int);
int p3 = va_arg(v, int);
count_overload3(p1, p2, p3);
break;
}
default:
{
va_end(v);
printf("Invalid arguments to function 'count_overload()'");
exit(1);
}
}
va_end(v);
}
#define count_overload(...)\
count_overload_aux(COUNT_PARMS(__VA_ARGS__), __VA_ARGS__)
int main(int argc, char const *argv[])
{
double d = 3.14;
count_overload(1);
count_overload(&d, "test");
count_overload('a',2,3);
return 0;
}
输出是:
One param: 1
Two params: 0x7ffc0fbcdd30 (3.140000) test
Three params: a 2 3
【问题讨论】:
-
这不是函数重载。这只是向编写源代码的开发人员模拟函数重载。
-
这对于开发人员来说看起来就像
count_overload是一个可变参数函数。您只是模糊了被调用函数所需的count参数,以了解它何时必须处理额外的参数,而不是从其他给定参数中隐式地知道这一点。 C 中的其他函数,例如printf,通过格式字符串包含的内容确定要访问的参数数量和类型。printf看起来与count_overload一样是“重载”函数。在这里的封面下,你没有超载任何东西。这只是可变参数。 -
然后在
count_overload_aux中存在开销,然后才开始实际调用真正的函数。总而言之,这是你在真实代码中永远不应该做的事情。 -
@BernardoDuarte:这一切都很好,很花哨,除了这会严重减少甚至消除编译时类型检查。因此,除非所有相关人员都确切地知道宏替换和参数解释发生了什么,否则您可能会遇到真正的调试问题。
-
如果你不关心编译时类型检查,那么只需使用类似 printf 的接口,其中第一个参数是描述以下参数的字符串。例如,
foo("dpi", 3.0, &x, 42),其中“格式”解释为d表示 double,p表示指向 int 的指针,i表示 int。对于开发人员来说,这比所有的宏废话更容易理解,它支持不同类型的等量参数,并且与宏解决方案相比既不安全也不安全。
标签: c overloading