0

我试过这个:

#define format(f, ...) \
                int size = strlen(f) + (sizeof((int[]){__VA_ARGS__})/sizeof(int)) + 1); \
                char *buf = malloc(size); \
                snprintf(buf, size, f, __VA_ARGS__); \
                buf

但它会返回很多语法错误。我该如何正确地做到这一点?

4

3 回答 3

3

C 宏不是函数,而是 1:1 替换。因此,如果您想像这样使用宏:

mystring = format("%d", 5);

你得到这个:

mystring = int size = strlen(f) + (sizeof((int[]){5})/sizeof(int)) + 1); \
            char *buf = malloc(size); \
            snprintf(buf, size, f, 5); \
            buf;

这没有任何意义。在您的情况下,您最好定义一个内联函数,该函数在体面的编译器上的性能应该不会更差。

如果它真的必须是一个宏并且你在 GCC 上,你可以使用复合语句来实现你的目标。它允许您这样做:mystring = ({ statement1, statement2, ..., statementN})它将在本地范围内执行您的所有语句,然后分配statementNmystring. 但是,它会使您的代码不可移植并且难以调试。

所以给你,但请不要在实际应用程序中使用它:

#define format(f, ...) \
    ({ int size = snprintf(NULL, 0, f, __VA_ARGS__) + 1;\
    char * buf = malloc(size);\
    snprintf(buf, size, f, __VA_ARGS__); buf; })

我是认真的。不要使用这个。使用内联函数。您还可以在普通函数中使用可变参数,使用va_argand va_start

inline char * format(f, ...) {
    va_list args;
    va_start(args, f);
    int size = vsnprintf(NULL, 0, f, args) + 1;
    char * buf = malloc(size);
    vsnprintf(buf, size, f, args);
    return buf;
}
于 2012-06-12T15:15:43.427 回答
0

如果你在没有参数的情况下使用它,你应该输入

snprintf(buf, size, f, ## __VA_ARGS__);

反而; 否则它不会截断结尾的逗号。

此外,如果你想使用格式字符串,你不能确定它strlen(format) + length of every other elements实际上是你得到的大小。您必须做出假设,然后使用安全功能。

使用这种宏语法也无法返回值。然而,使用 GNU 扩展是可能的。请参阅下面的修改后的答案。

还有,你想做什么

sizeof((int[]){__VA_ARGS__}

? 这一点都不好。您无法找出可变参数列表的大小。

尝试这样的事情:

#define format(f, ...) \
            ({
            char *buf = malloc(4096); \
            snprintf(buf, 4096, f , ## __VA_ARGS__); \
            buf
        })

希望这可以帮助。

于 2012-06-12T15:13:11.590 回答
0

不知道你想用第一行做什么。您似乎正在尝试计算参数的数量,但随后您将其传递给malloc并将返回值malloc用作大小..?!

分配空间的正确方法snprintf是首先调用snprintf缓冲区指针和大小为零,然后检查返回值。返回值加一(用于空终止)将为您提供需要分配并传递给第二次snprintf调用的大小。

另外,不要尝试使用宏来执行此操作;使用函数和vsnprintf

于 2012-06-12T15:14:30.790 回答