2009-09-29 79 views
6

我在一个巨大的程序中有大量的my_printf()函数调用。我现在要将它们全部转换,以便该函数接受一个新的整数参数(称为x),而不必编辑大量的调用。如果my_printf永远只花了只有一个字符串参数然后我可以做这样的事情:#define和具有可变长度参数的函数

#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 
} 

回答

7

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

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

由于Microsoft's implementation个suppresse尾随逗号,所述str参数可以被明确地加入

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

但是当没有可变参数

my_printf("foo") 

或空的参数列表

调用这将导致在标准C语法错误
my_printf("foo",) 

因此,我会去第一个版本。

7

最好的办法当然是硬着头皮和编辑代码。否则,你正在创造一个“神秘”,这需要所有未来的代码维护者来解决。即使那只是你,这正是你会忘记所有关于这种聪明的伎俩。它很难回来,并被奇怪的毫无意义的宏所困惑。

也就是说,如果你使用的是GNU工具链,你也许可以使用varargs macros来看看。

+0

+1咬子弹。有了今天的编辑们重构支持等,你应该笑。哎呀,15年前我的编程编辑器可以非常容易地进行全局搜索,并在整个目录树中替换由通配符指定的文件,无论我是否先预览结果。 (如果你想宏观,那么你可以盲目地做。) – 2009-09-29 10:41:33

+0

看我编辑原始问题 – Mick 2009-09-29 11:08:21

+0

+1。把它看作是一个学习机会,以便真正掌握现代编辑器可以做什么(或者如果你足够长的时间,Vim或Emacs能做什么 - 他们可以做的事情,Visual Studio只是捕捉与......一起)。 – AAT 2009-09-29 15:40:06

8

如果代码可以编译为C99的代码,你可以定义一个variadic macro

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

预处理器将取代参数...和GNU预处理器将删除后面的逗号的情况下,宏调用只有str参数。

+2

这是GNU,而不是C99 - C99版本会读取'define my_printf(str,...)_my_printf(x,__VA_ARGS __)';请记住,你还需要提供一个参数 – Christoph 2009-09-29 10:43:25

+0

,你和我都忘记传递'str';我认为最好的方法实际上是完全删除显式的'str',并使用'define my_printf(...)_my_printf(x,__VA_ARGS __)',这样即使在C99版本中也可以不使用函数的变参数来调用它。 – Christoph 2009-09-29 11:59:59

+0

问题现在已解决。我正在使用dev-studio 2008,而__VA_ARGS__这个东西很有用 - 但我不确定哪个答案是正确的,因为它们都没有真正被发现。 unwind的答案意味着我需要使用GNU,phillipe的答案也有错误。 – Mick 2009-09-29 12:05:47

0

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

2

不符合标准的C89宏,你不能。然而,你可以使用的功能,打破了你的my_printf功能的主要部分为vmy_printf功能,analagous的标准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; 
} 

(这种事情是为什么那些诉..所有标准版本的可变参数功能存在)

0

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

#define my_printf(x) printf x 

(注意没有大括号)

称呼它,使用:

my_printf((any number of arguments)) 

(注意双括号)