{"id":3921,"date":"2020-01-04T01:01:23","date_gmt":"2020-01-04T09:01:23","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3921"},"modified":"2019-12-28T10:05:11","modified_gmt":"2019-12-28T18:05:11","slug":"the-snprintf-function","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3921","title":{"rendered":"The <em>snprintf()<\/em> Function"},"content":{"rendered":"<p>Another non-standard library function is <em>snprintf()<\/em>. Like the <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3873\"><em>strlcpy()<\/em><\/a> and <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3896\"><em>strlcat()<\/em><\/a> functions shown in previous Lessons, <em>snprintf()<\/em> is safer than its standard Library counterpart, <em>sprintf()<\/em>.<br \/>\n<!--more--><br \/>\nThe <em>sprintf()<\/em> function is part of the family of <em>printf()<\/em> functions, each of which formats output. Here is its <em>man<\/em> page format:<\/p>\n<p><code>int sprintf(char * restrict str, const char * restrict format, ...);<\/code><\/p>\n<p>The function&#8217;s first argument is a buffer into which the formatted output is placed. No bounds-checking is performed, so the buffer can overflow, as the following code demonstrates:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n\r\nint main()\r\n{\r\n    char buffer[12];\r\n    int r;\r\n\r\n    r = sprintf(buffer,\"The total is %d\\n\",5+8);\r\n\r\n    puts(buffer);\r\n    printf(\"%d characters stored\\n\",r);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>This code saves the <em>sprintf()<\/em> function&#8217;s return value. As with <em>printf()<\/em>, this value is equal to the characters output, or negative for an error. Here&#8217;s a sample run under Ubuntu Linux:<\/p>\n<p><code>The total is 13<\/p>\n<p>16 characters stored<\/code><\/p>\n<p>The output on my Macintosh is far more telling:<\/p>\n<p><code>Illegal instruction: 4<\/code><\/p>\n<p>Even when the program doesn&#8217;t crash, you can see that 16 characters were stored in a 12 character buffer. The <em>snprintf()<\/em> function prevents this overflow from occurring. Here is its <em>man<\/em> page format:<\/p>\n<p><code>int snprintf(char * restrict str, size_t size, const char * restrict format, ...);<\/code><\/p>\n<p>As with <em>sprintf()<\/em>, the first argument is a buffer into which the formatted output is stored. A new second argument sets the buffer&#8217;s size. This <code>size<\/code> value caps the string at <em>n<\/em>-1 characters (one for the null character), preventing overflow. Here is the <em>snprintf()<\/em> version of the 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[12];\r\n    int r;\r\n\r\n    r = snprintf(buffer,12,\"The total is %d\\n\",5+8);\r\n\r\n    puts(buffer);\r\n    printf(\"%d characters stored\\n\",r);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>And sample output:<\/p>\n<p><code>The total i<br \/>\n16 characters stored<\/code><\/p>\n<p>The output is capped at 12 bytes; 11 for the string and one for the null character.<\/p>\n<p>The return value, 16, is the same as for the <em>sprintf()<\/em> function. The logic here is that the return value can be compared with the function&#8217;s second argument to determine whether overflow would have occurred.<\/p>\n<p>Coding my own <em>snprintf()<\/em> function would be truly complex. Not only must I emulate its behavior, but I must also reverse engineer the <em>printf()<\/em> function; as a standard I\/O function, I couldn&#8217;t include its definition in <code>stdio.h<\/code>, which truly complicates matters.<\/p>\n<p>Next week, I explore another interesting variation on the <em>printf()<\/em> function, <em>asprintf()<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The <em>sprintf()<\/em> can lead to buffer overflow, which is why the non-standard <em>snprintf()<\/em> function was developed. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3921\">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-3921","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\/3921","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=3921"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3921\/revisions"}],"predecessor-version":[{"id":3935,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3921\/revisions\/3935"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}