如何编写一个执行malloc的宏,格式化一个字符串然后返回格式化的字符串?

时间:2012-06-12 15:10:05

标签: c macros

我试过这个:

#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

但它会返回很多语法错误。我该怎么做呢?

3 个答案:

答案 0 :(得分: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})将执行本地范围内的所有语句,然后将statementN分配给mystring。但是它会使你的代码变得不可移植并且无法进行调试。

所以你去了,但请不要在实际应用中使用它:

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

我很认真。不要使用它。使用内联函数。您还可以使用va_argva_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;
}

答案 1 :(得分: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
        })

希望这有帮助。

答案 2 :(得分:0)

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

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

另外,不要试图用宏来做这件事;使用函数和vsnprintf