#define和具有可变长度参数的函数

时间:2009-09-29 10:30:39

标签: c

我在一个庞大的程序中有数以万计的my_printf()函数调用。我现在想要将它们全部转换,以便函数采用一个新的整数参数(称之为x),而不必编辑数以万计的调用。如果my_printf只采用了一个字符串参数,那么我可以这样做:

    #define my_printf(str) _my_printf(x,str)

    void _my_printf(int x,char *str) // changed from my_printf(char *str)
    {
        // stuff
    }

但是由于my_printf采用了可变数量的参数,我不知道该怎么做。可以吗?

编辑:对于那些想知道我为什么要这样做的人,这是一个相关的例子:

#if BELT_AND_BRACES_DIAGNOSTIC_MODE
    #define function(x) _function(__FILE__,__LINE__,x)
#else // speed critical optimised mode
    #define function(x) _function(x)
#endif

#if BELT_AND_BRACES_DIAGNOSTIC_MODE
    void _function(char *file,int line,int x)
#else
    void _function(int x)
#endif
{
    // stuff
    #if BELT_AND_BRACES_DIAGNOSTIC_MODE
    if (something_went_wrong)
    {
        printf("Cock up in function when called from %s line %d\n",file,line);
    }
    #endif
}

6 个答案:

答案 0 :(得分:8)

如果代码可以编译为C99代码,则可以定义variadic macro

#define my_printf(str, args...) _my_printf(x, str, ##__VA_ARGS__)

预处理器将替换参数......如果仅使用str参数调用宏,GNU预处理器将删除尾随逗号。

答案 1 :(得分:7)

最好的事情当然是咬紧牙关并编辑代码。否则你就会创造一个“神秘”,需要所有未来的代码维护者来解决。即使那只是你,这正是你会忘记的那种聪明的伎俩。它很难回来,并被奇怪的无意义的宏所迷惑。

也就是说,如果您使用的是GNU工具链,您可以考虑使用varargs macros

答案 2 :(得分:7)

您可以使用C99可变参数宏:

#define my_printf(...) my_printf_(x, __VA_ARGS__)

由于Microsoft's implementation支持尾随逗号,可以明确添加str参数

#define my_printf(str, ...) my_printf_(x, str, __VA_ARGS__)

但是这会在没有可变参数的情况下调用标准C时导致语法错误

my_printf("foo")

或空参数列表

my_printf("foo",)

因此,我会选择第一个版本。

答案 3 :(得分:2)

不是标准的C89宏,你不能。但是,您可以使用函数获得相同的效果,将my_printf函数的主要部分分解为vmy_printf函数,与标准vprintf类似:

#include <stdarg.h>

int vmy_printf(int x, const char *format, va_list ap)
{
    /* main body of my_printf goes here, taking its varargs from ap */
}

/* new_my_printf(), for callers who know about the x parameter */
int new_my_printf(int x, const char *format, ...)
{
    int n;
    va_list ap;

    va_start(ap, format);
    n = vmy_printf(x, format, ap);
    va_end(ap);

    return n;
}

/* my_printf(), for the old callers who don't know about x */
int my_printf(const char *format, ...)
{
    int n;
    va_list ap;

    va_start(ap, format);
    n = vmy_printf(DEFAULT_X, format, ap);
    va_end(ap);

    return n;
}

(这种事情为什么存在所有标准varargs函数的那些v ...版本。)

答案 4 :(得分:0)

如果my_printf已经采用了可变数量的参数,我不确定为什么需要在宏中包含“再多一个参数”...只需插入带有额外参数的新调用并完成用它;旧的电话仍应按预期工作。

答案 5 :(得分:0)

解决这个问题的一个简单方法是......

#define my_printf(x) printf x

(注意缺少的大括号)

要拨打电话,请使用:

my_printf((any number of arguments))

(注意双括号)