Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Building on <a href="https://stackoverflow.com/users/5353/sylvain-defresne">Sylvain</a>'s <a href="https://stackoverflow.com/a/4899487/15168">answer</a>, here is a simple implementation with both <code>asprintf()</code> and <code>vasprintf()</code> because where you need one, you usually end up needing the other too. And, given the <code>va_copy()</code> macro from C99, it is easy to implement <code>asprintf()</code> in terms of <code>vasprintf()</code>. Indeed, when writing varargs functions, it is very often helpful to have them in pairs, one with the ellipsis notation and one with the <code>va_list</code> argument in place of the ellipsis, and you trivially implement the former in terms of the latter.</p> <p>This leads to the code:</p> <pre><code>int vasprintf(char **ret, const char *format, va_list args) { va_list copy; va_copy(copy, args); /* Make sure it is determinate, despite manuals indicating otherwise */ *ret = NULL; int count = vsnprintf(NULL, 0, format, args); if (count &gt;= 0) { char *buffer = malloc(count + 1); if (buffer == NULL) count = -1; else if ((count = vsnprintf(buffer, count + 1, format, copy)) &lt; 0) free(buffer); else *ret = buffer; } va_end(copy); // Each va_start() or va_copy() needs a va_end() return count; } int asprintf(char **ret, const char *format, ...) { va_list args; va_start(args, format); int count = vasprintf(ret, format, args); va_end(args); return(count); } </code></pre> <p>The tricky part of using these functions in a system where they are not provided is deciding where the functions should be declared. Ideally, they'd be in <code>&lt;stdio.h&gt;</code>, but then you wouldn't need to write them. So, you have to have some other header which includes <code>&lt;stdio.h&gt;</code> but declares these functions if they are not declared in <code>&lt;stdio.h&gt;</code>. And, ideally, the code should semi-automatically detect this. Maybe the header is <code>"missing.h"</code>, and contains (in part):</p> <pre><code>#ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include &lt;stdio.h&gt; #include &lt;stdarg.h&gt; #ifndef HAVE_ASPRINTF extern int asprintf(char **ret, const char *format, ...); extern int vasprintf(char **ret, const char *format, va_list args); #endif /* HAVE_ASPRINTF */ </code></pre> <p>Also, note that this man page for <a href="http://linux.die.net/man/3/asprintf" rel="nofollow noreferrer">asprintf()</a> says that the return value in the pointer is indeterminate in case of error. Other <a href="http://www.manpagez.com/man/3/asprintf/" rel="nofollow noreferrer">man pages</a>, including the one referenced in the question, indicate that it is explicitly set to NULL on error. The C Standard committee document (<a href="http://open-std.org/jtc1/sc22/wg14/www/docs/n1337.pdf" rel="nofollow noreferrer">n1337.pdf</a>) does not specify the error behaviour on lack of memory.</p> <ul> <li>If using asprintf(), do not assume that the pointer is initialized if the function fails.</li> <li>If implementing asprintf(), ensure that the pointer is set to null on error to give deterministic behaviour. </li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload