C 为什么在for循环中声明va_列表?

C 为什么在for循环中声明va_列表?,c,C,以下代码来自better字符串库标题。 在查看define宏时,我注意到va_list、va_start和va_end都在for循环中使用 想知道为什么这是必要的吗 顺便说一下,我已经研究了bvcformata函数,它不修改bstrmp_arglist #define bvformata(ret, b, fmt, lastarg) { \ bstring bstrtmp_b = (b); \ const char * bstrtmp_fmt = (fmt); \

以下代码来自better字符串库标题。 在查看define宏时,我注意到va_list、va_start和va_end都在for循环中使用

想知道为什么这是必要的吗

顺便说一下,我已经研究了bvcformata函数,它不修改bstrmp_arglist

#define bvformata(ret, b, fmt, lastarg) { \
        bstring bstrtmp_b = (b); \
        const char * bstrtmp_fmt = (fmt); \
        int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
        for (;;) { \
                va_list bstrtmp_arglist; \
                va_start (bstrtmp_arglist, lastarg); \
                bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
                va_end (bstrtmp_arglist); \
                if (bstrtmp_r >= 0) { /* Everything went ok */ \
                        bstrtmp_r = BSTR_OK; \
                        break; \
                } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
                        bstrtmp_r = BSTR_ERR; \
                        break; \
                } \
                bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
        } \
        ret = bstrtmp_r; \
}

#endif
#定义bvformata(ret、b、fmt、lastarg){\
bstring bstrtmp_b=(b)\
常量字符*bstrtmp_fmt=(fmt)\
int bstrtmp_r=BSTR_ERR,bstrtmp_sz=16\
对于(;){\
va_列表bstrtmp_参数列表\
va_开始(bstrtmp_参数列表,最后参数)\
bstrtmp_r=bvcformata(bstrtmp_b、bstrtmp_sz、bstrtmp_fmt、bstrtmp_arglist)\
va_端(bstrtmp_参数列表)\
如果(bstrtmp_r>=0){/*一切正常*/\
bstrtmp_r=BSTR_OK\
中断\

}else if(-bstrtmp\u r别介意愚蠢的我。我只是注意到for循环中存在“break”。通过“moving”va_list和va_end out将产生内存泄漏。

您可以将
va_list
声明移到循环之外。但是
va_start
va_end
必须留在循环中,这样对
bvcformata()
的每次调用都将从头开始处理变量参数

#define bvformata(ret, b, fmt, lastarg) { \
        bstring bstrtmp_b = (b); \
        const char * bstrtmp_fmt = (fmt); \
        int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
        va_list bstrtmp_arglist; \
        for (;;) { \
                va_start (bstrtmp_arglist, lastarg); \
                bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
                va_end (bstrtmp_arglist); \
                if (bstrtmp_r >= 0) { /* Everything went ok */ \
                        bstrtmp_r = BSTR_OK; \
                        break; \
                } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
                        bstrtmp_r = BSTR_ERR; \
                        break; \
                } \
                bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
        } \
        ret = bstrtmp_r; \
}

#endif
#定义bvformata(ret、b、fmt、lastarg){\
bstring bstrtmp_b=(b)\
常量字符*bstrtmp_fmt=(fmt)\
int bstrtmp_r=BSTR_ERR,bstrtmp_sz=16\
va_列表bstrtmp_参数列表\
对于(;){\
va_开始(bstrtmp_参数列表,最后参数)\
bstrtmp_r=bvcformata(bstrtmp_b、bstrtmp_sz、bstrtmp_fmt、bstrtmp_arglist)\
va_端(bstrtmp_参数列表)\
如果(bstrtmp_r>=0){/*一切正常*/\
bstrtmp_r=BSTR_OK\
中断\

}else if(-bstrtmp\u r)你为什么这么认为?你更新的代码在循环外调用
va\u end
。如果
va\u list
是指针,我认为不能保证
va\u arg()
不会取消指针引用并修改内容。如果我在公司代码中看到这种宏,我会强迫作者在黑板上写1000次“我再也不会写这样的东西了”
#define bvformata(ret, b, fmt, lastarg) { \
        bstring bstrtmp_b = (b); \
        const char * bstrtmp_fmt = (fmt); \
        int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
        va_list bstrtmp_arglist; \
        for (;;) { \
                va_start (bstrtmp_arglist, lastarg); \
                bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
                va_end (bstrtmp_arglist); \
                if (bstrtmp_r >= 0) { /* Everything went ok */ \
                        bstrtmp_r = BSTR_OK; \
                        break; \
                } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
                        bstrtmp_r = BSTR_ERR; \
                        break; \
                } \
                bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
        } \
        ret = bstrtmp_r; \
}

#endif