{"id":3934,"date":"2020-01-11T00:01:23","date_gmt":"2020-01-11T08:01:23","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3934"},"modified":"2020-01-04T09:33:53","modified_gmt":"2020-01-04T17:33:53","slug":"fun-with-the-asprintf-function","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3934","title":{"rendered":"Fun with the <em>asprintf()<\/em> Function"},"content":{"rendered":"<p>If you desire to store formatted output in a buffer, the <em>snprintf()<\/em> function, covered in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3921\">last week&#8217;s Lesson<\/a>, is a safe alternative to the standard Library <em>sprintf()<\/em> function. An even better choice is the <em>asprintf()<\/em> function.<br \/>\n<!--more--><br \/>\nThe <em>asprintf()<\/em> function sends formatted output into a perfectly-sized buffer, allocated within the function itself. Here is its <em>man<\/em> page format:<\/p>\n<p><code>int asprintf(char **ret, const char *format, ...);<\/code><\/p>\n<p>The first argument is the scary pointer-pointer thing, but it&#8217;s really the address of a pointer. When the function returns, the pointer contains the formatted output string; the final two arguments are the same as for the standard <em>printf()<\/em> function: a format string and variable argument list.<\/p>\n<p>Sample code:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char *buffer;\r\n    int r;\r\n\r\n    r = asprintf(&amp;buffer,\"The total is %d\\n\",5+8);\r\n\r\n    puts(buffer);\r\n    printf(\"%d characters generated\\n\",r);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The <em>char<\/em> pointer <code>buffer<\/code> is declared at Line 5. Its address is passed to the <em>asprintf()<\/em> function at Line 8.<\/p>\n<p>Within the <em>asprintf()<\/em> function, the buffer is allocated, the size properly set to be filled with the formatted output. No overflow is possible.<\/p>\n<p>The buffer&#8217;s contents are output at Line 11. The <em>asprintf()<\/em> function&#8217;s return value, stored in variable <code>r<\/code>, is also output. This value is equal to the length of the string returned (the size of the buffer, minus one for the null character):<\/p>\n<p><code>The total is 13<\/p>\n<p>16 characters generated<\/code><\/p>\n<p>Using this function is far safer than using the <em>sprintf()<\/em> function, which doesn&#8217;t check for buffer overflow. And it&#8217;s better than the <em>snprintf()<\/em> function, which has a set buffer size. With the <em>asprintf()<\/em> function, the buffer size can be anything; all you must do is supply a <em>char<\/em> pointer to reference the string created. Well, and get over any double-pointer fears you harbor. Speaking of which, here is the double-pointer version of the same code:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char **buffer;\r\n    int r;\r\n\r\n    r = asprintf(buffer,\"The total is %d\\n\",5+8);\r\n\r\n    puts(*buffer);\r\n    printf(\"%d characters generated\\n\",r);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The double-pointer <code>buffer<\/code> is declared at Line 5. It&#8217;s passed directly as the first argument of <em>asprintf()<\/em> at Line 8; no need to prefix it with an ampersand.<\/p>\n<p>Line 10 uses the <code>*buffer<\/code> argument in the <em>puts()<\/em> function. The format <code>*buffer<\/code> refers to the string, whereas <code>**buffer<\/code> refers to the string&#8217;s address. Yes, it&#8217;s all complicated pointer nonsense, yet the code runs identically to the first example.<\/p>\n<p>If you the <code>-Wall<\/code> switch to build this second example of the code, you may see an uninitialized pointer warning. Ignore it. The warning is legitimate but the fix, which is to initialize the pointer to <em>NULL<\/em>, may crash the program. It&#8217;s safe to pass the uninitialized <code>**buffer<\/code> pointer to the <em>asprintf()<\/em> function because the function itself initializes it.<\/p>\n<p>The <code>**buffer<\/code> or <code>&buffer<\/code> format is required because a pointer must be passed indirectly to a function that modifies the pointer&#8217;s address. Otherwise the function loses the pointer&#8217;s address when it returns, which defeats the purpose. You can read my <a href=\"http:\/\/c-for-dummies.com\/blog\/?p=2288\">series of Lessons<\/a> on this topic if it confuses you or you need to brush-up.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A smart function, <em>asprintf()<\/em> both allocates and sizes a buffer into which formatted output is stored. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3934\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-3934","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3934"}],"version-history":[{"count":3,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3934\/revisions"}],"predecessor-version":[{"id":3939,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3934\/revisions\/3939"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3934"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3934"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}