Unix to Windows: Alternative to vsnprintf to determine length?
我目前正在将我们的Linux库之一的代码转换为Windows DLL。
在该库中,我有一个函数,该函数采用printf-way(格式字符串,
然后省略号)。在此函数中,我使用vsnprintf格式化提供的参数。
因为我想知道我是否可以将最终字符串塞进一个小的缓冲区中,还是必须分配
对于它的内存,我对确定格式化字符串的"将要长度"感兴趣。
为此,我目前正在像这样使用vsnprintf(显然是示例代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
开放组基本规范第6期涵盖了此用法:
vsnprintf(char *restrict s, size_t n, const char *restrict format, va_list ap)
The [...] vsnprintf() [...] functions shall be equivalent to [...] snprintf().
snprintf(char *restrict s, size_t n, const char *restrict format, ...)
If the value of n is zero on a call to snprintf(), nothing shall be written, the number of bytes that would have been written had n been sufficiently large excluding the terminating null shall be returned, and s may be a null pointer.
当我在启用/ analyze的Windows系统(Visual Studio 2010)上编译此代码时出现了问题。编译器/分析器给了我以下内容:
test.c(11) : warning C6309: Argument '1' is null: this does not adhere to function specification of 'vsnprintf'
test.c(11) : warning C6387: 'argument 1' might be '0': this does not adhere to the specification for the function 'vsnprintf': Lines: 7, 8, 10, 11
快速查看vsnprintf的MSDN条目,就可以得出以下结论:
If buffer or format is NULL, or if count is less than or equal to zero, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions return -1.
很好奇的是,以上示例仍在Windows上"按预期"运行(即,它向我返回了将要写入的字符数)。
但是由于我不想让它依赖未指定的东西,所以我想知道是否有更好的官方方法来实现这一目标,而不必希望这不会在将来的发行版中打破。
谢谢你的时间!
汉斯·帕桑特(Hans Passant)在评论中提供的答案:
_vscprintf文档在Windows上提供了此功能,
因此不必依赖"未指定的行为"。
从snprintf的手册页中获取以下示例:
这是分配缓冲区以适合您的字符串的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) { int n; int size = 100; /* Guess we need no more than 100 bytes. */ char *p, *np; va_list ap; if ((p = malloc(size)) == NULL) return NULL; while (1) { /* Try to print in the allocated space. */ va_start(ap, fmt); n = vsnprintf(p, size, fmt, ap); va_end(ap); /* If that worked, return the string. */ if (n > -1 && n < size) return p; /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n+1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ if ((np = realloc (p, size)) == NULL) { free(p); return NULL; } else { p = np; } } } |