在windows上使用asprintf()

我已经写了一个C程序,完美的在linux上工作,但是当我在Windows上编译它,它给了我一个错误,说asprintf()是未定义的。 它应该是stdio库的一部分,但似乎许多编译器不包括它。 我可以使用哪个编译器来使用asprintf()函数? 我已经尝试了多个编译器,但似乎没有定义它。

asprintf()函数不是C语言的一部分,并不适用于所有平台。 Linux有这个事实是不寻常的

您可以使用_vscprintf_vsprintf_s编写自己的_vsprintf_s

 int vasprintf(char **strp, const char *fmt, va_list ap) { // _vscprintf tells you how big the buffer needs to be int len = _vscprintf(fmt, ap); if (len == -1) { return -1; } size_t size = (size_t)len + 1; char *str = malloc(size); if (!str) { return -1; } // _vsprintf_s is the "secure" version of vsprintf int r = _vsprintf_s(str, len + 1, fmt, ap); if (r == -1) { free(str); return -1; } *strp = str; return r; } 

这是来自内存,但它应该非常接近您将如何编写Visual Studio运行时的vasprintf

使用_vscprintf_vsprintf_s是Microsoft C运行时特有的_vscprintf _vsprintf_s ,您不会在Linux或OS X上以这种方式编写代码。特别是_s版本,虽然标准化,实际上并不经常在Microsoft生态系统之外遇到,而_vscprintf在其他地方甚至不存在。

当然, asprintf只是asprintf的一个包装:

 int asprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int r = vasprintf(strp, fmt, ap); va_end(ap); return r; } 

这不是一个“便携”的方式来编写asprintf ,但如果你唯一的目标是支持Linux + Darwin + Windows,那么这是最好的方法。

asprintf()不是C标准函数。 这是一个由glibc提供的GNU扩展。 因此它适用于Linux。 但其他C实现可能不提供它 – 这似乎是您的图书馆的情况。

你可以使用标准的C函数malloc()snprintf()重写你的代码。

这个函数在glibc libary中,不受Windows的支持。

据我所知,asprintf与sprintf类似,缓冲区分配在其中。

在Windows中,最简单的方法可能是编写自己的实现。 要计算要分配的缓冲区的大小,只需使用如下所示:

int size_needed = snprintf(NULL,0,“%s \ n”,“test”);

一旦大小被计算,只需分配缓冲区,调用snprintf格式化字符串并返回指针。

asprintf()多平台实现

基于@DietrichEpp和@MarcusSun在这个线程中的回答,以及在另一个线程中这个针对MacOS / Linux的_vscprintf() 协作实现 。 在GCC / Linux,MSVC / Windows,MinGW / Windows(通过Code :: Blocks的TDM-GCC)测试。 应该也希望在Android上工作。

头文件

(大概叫asprintf.h 。)

 #include <stdio.h> /* needed for vsnprintf */ #include <stdlib.h> /* needed for malloc-free */ #include <stdarg.h> /* needed for va_list */ #ifndef _vscprintf /* For some reason, MSVC fails to honour this #ifndef. */ /* Hence function renamed to _vscprintf_so(). */ int _vscprintf_so(const char * format, va_list pargs) { int retval; va_list argcopy; va_copy(argcopy, pargs); retval = vsnprintf(NULL, 0, format, argcopy); va_end(argcopy); return retval;} #endif // _vscprintf #ifndef vasprintf int vasprintf(char **strp, const char *fmt, va_list ap) { int len = _vscprintf_so(fmt, ap); if (len == -1) return -1; char *str = malloc((size_t) len + 1); if (!str) return -1; int r = vsnprintf(str, len + 1, fmt, ap); /* "secure" version of vsprintf */ if (r == -1) return free(str), -1; *strp = str; return r;} #endif // vasprintf #ifndef asprintf int asprintf(char *strp[], const char *fmt, ...) { va_list ap; va_start(ap, fmt); int r = vasprintf(strp, fmt, ap); va_end(ap); return r;} #endif // asprintf 

用法

 #include <stdio.h> /* needed for puts */ #include <stdlib.h> /* needed for free */ #include "asprintf.h" int main(void) { char *b; asprintf(&b, "Mama %s is equal %d.", "John", 58); puts(b); /* Expected: "Mama John is equal 58." */ free(b); /* Important! */ return 0; } 

现场示例: rex( MSVC · gcc · clang )| repl.it | tio.run | 键盘 | ide1( gcc · clang · C99 )