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

时间:2021-04-20 18:28:41

I have zillions of my_printf() function calls in a huge program. I now want to convert them all so that the function takes a new integer argument (call it x) without having to edit the zillions of calls. If my_printf only ever took exactly one string argument then I could do something like this:

我在一个庞大的程序中有数以万计的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
    }

But as my_printf takes a variable number of arguments I'm not sure how to do it. Can it be done?

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

EDIT: for those wondering why I should want to do such a thing, here's a related example:

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

#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 个解决方案

#1


7  

You may use C99 variadic macros:

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

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

As Microsoft's implementation suppresse trailing commas, the str argument can be added explicitly

由于Microsoft的实现支持尾随逗号,因此可以显式添加str参数

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

but this would lead to a syntax error in standard C when invoked without variadic arguments

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

my_printf("foo")

or an empty argument list

或一个空的参数列表

my_printf("foo",)

Therefore, I'd go with the first version.

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

#2


8  

If the code can be compiled as C99 code, you can define a variadic macro

如果代码可以编译为C99代码,则可以定义可变参数宏

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

The preprocessor will replace the arguments ... and the GNU preprocessor will remove the trailing comma in case the macro is invoked only with the str argument.

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

#3


7  

The best thing is of course to bite the bullet and edit the code. Otherwise you're creating a "mystery", that needs to be solved by all future maintainers of the code. Even if that's only you, this is exactly the kind of clever trick that you will forget all about. It sucks to come back, and be puzzled by strange pointless-seeming macros.

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

That said, if you're using a GNU toolchain, you can perhaps look into using varargs macros.

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

#4


2  

Not with standard C89 macros, you can't. However you can get the same effect using functions, by breaking out the main part of your my_printf function into a vmy_printf function, analagous to the standard vprintf:

不是标准的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;
}

(This kind of thing is why those v... versions of all the standard varargs functions exist.)

(这就是为什么存在所有标准varargs函数的v ...版本的原因。)

#5


0  

If my_printf already takes a variable number of arguments, I'm not sure why you need to wrap 'one more argument' in a macro... Just insert the new calls with the extra argument and be done with it; the old calls should still work as expected.

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

#6


0  

A simple solution to this problem is...

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

#define my_printf(x) printf x

(note the missing braces)

(注意缺少的大括号)

To call it, use:

要打电话,请使用:

my_printf((any number of arguments))

(note the double braces)

(注意双括号)

#1


7  

You may use C99 variadic macros:

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

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

As Microsoft's implementation suppresse trailing commas, the str argument can be added explicitly

由于Microsoft的实现支持尾随逗号,因此可以显式添加str参数

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

but this would lead to a syntax error in standard C when invoked without variadic arguments

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

my_printf("foo")

or an empty argument list

或一个空的参数列表

my_printf("foo",)

Therefore, I'd go with the first version.

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

#2


8  

If the code can be compiled as C99 code, you can define a variadic macro

如果代码可以编译为C99代码,则可以定义可变参数宏

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

The preprocessor will replace the arguments ... and the GNU preprocessor will remove the trailing comma in case the macro is invoked only with the str argument.

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

#3


7  

The best thing is of course to bite the bullet and edit the code. Otherwise you're creating a "mystery", that needs to be solved by all future maintainers of the code. Even if that's only you, this is exactly the kind of clever trick that you will forget all about. It sucks to come back, and be puzzled by strange pointless-seeming macros.

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

That said, if you're using a GNU toolchain, you can perhaps look into using varargs macros.

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

#4


2  

Not with standard C89 macros, you can't. However you can get the same effect using functions, by breaking out the main part of your my_printf function into a vmy_printf function, analagous to the standard vprintf:

不是标准的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;
}

(This kind of thing is why those v... versions of all the standard varargs functions exist.)

(这就是为什么存在所有标准varargs函数的v ...版本的原因。)

#5


0  

If my_printf already takes a variable number of arguments, I'm not sure why you need to wrap 'one more argument' in a macro... Just insert the new calls with the extra argument and be done with it; the old calls should still work as expected.

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

#6


0  

A simple solution to this problem is...

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

#define my_printf(x) printf x

(note the missing braces)

(注意缺少的大括号)

To call it, use:

要打电话,请使用:

my_printf((any number of arguments))

(note the double braces)

(注意双括号)