{"id":3398,"date":"2018-12-08T00:01:19","date_gmt":"2018-12-08T08:01:19","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=3398"},"modified":"2018-12-08T08:56:28","modified_gmt":"2018-12-08T16:56:28","slug":"variable-argument-lists","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=3398","title":{"rendered":"Variable Argument Lists"},"content":{"rendered":"<p>I&#8217;ve often wondered how it works. The <em>printf()<\/em> function has one argument minimum, a formatting string. Yet how does the compiler know how many other arguments are required? It&#8217;s not really a mystery, once you understand the concept of variable argument lists.<br \/>\n<!--more--><br \/>\nHere is the <em>man<\/em> page format for the <em>printf()<\/em> function:<\/p>\n<p><code>int printf(const char * restrict format, ...);<\/code><\/p>\n<p><code>const char * restrict format<\/code> is a single argument, the first. The second argument is <code>...<\/code> (three dots or an ellipses), which is a declaration. It means any number of arguments (including zero) can appear at that point in the function. The official term for such a declaration is a <em>variable argument list<\/em>.<\/p>\n<p>To process the variable argument list, four macros are used:<\/p>\n<p><em>va_list<br \/>\nva_start()<br \/>\nva_arg()<br \/>\nva_end()<\/em><\/p>\n<p>Each of these is required to read whatever arguments were passed to the function, replacing the <code>...<\/code> declaration.<\/p>\n<p>To make the variable argument list work, the first argument passed to the function must set the number of arguments the <code>...<\/code> declaration represents. You can&#8217;t just pass any old number of arguments. For example:<\/p>\n<p><code>list( 5, 1, 2, 3, 4, 5 );<\/code><\/p>\n<p>The <em>list()<\/em> function&#8217;s declaration is <code>list(int a, ...)<\/code>. The first argument, 5, represents the number of items passed.<\/p>\n<p>In the <em>printf()<\/em> function, the first argument is parsed internally to determine the number of required arguments. Once you know that value, you can use the four macros to write the code required to read the variable argument list:<\/p>\n<p>The <em>va_list<\/em> macro declares a variable representing each argument. This variable is used by the other three macros.<\/p>\n<p>The <em>va_start()<\/em> macro is passed two arguments: the <em>va_list<\/em> variable and the count value of arguments expected.<\/p>\n<p>The <em>va_arg()<\/em> macro extracts each argument, one after the other. It requires two arguments: the <em>va_list<\/em> variable and a data type (<em>int<\/em>, <em>char<\/em>, <em>float<\/em>, and so on).<\/p>\n<p>When all the fun is complete, the <em>va_end()<\/em> macro terminates the operation, cleaning up whatever memory was used when the <em>va_end<\/em> variable was declared.<\/p>\n<p>In the following code, the <em>list()<\/em> function accepts variable arguments. The first argument is the argument count. The rest of the values are displayed from within the function:<\/p>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdarg.h&gt;\r\n\r\nvoid list(int a, ... )\r\n{\r\n    va_list arg_list;    <span class=\"comments\">\/* variable argument list variable *\/<\/span>\r\n    int x;\r\n\r\n    <span class=\"comments\">\/* begin processing *\/<\/span>\r\n    va_start(arg_list,a);\r\n    printf(\"Passed:\");\r\n    for(x=0;x&lt;a;x++)\r\n    {\r\n        <span class=\"comments\">\/* fetch values *\/<\/span>\r\n        printf(\" %2d\",va_arg(arg_list,int) );\r\n    }\r\n    putchar('\\n');\r\n    <span class=\"comments\">\/* clean up *\/<\/span>\r\n    va_end(arg_list);\r\n}\r\n\r\nint main()\r\n{\r\n    list( 5, 1, 2, 3, 4, 5 );\r\n    list( 3, 40, 60, 10 );\r\n\r\n    return(0);\r\n}<\/pre>\n<p>At Line 6, the <em>va_list<\/em> variable <code>arg_list<\/code> is created. It&#8217;s used in the rest of the function to handle the variable argument list.<\/p>\n<p>At Line 10, the <em>va_start()<\/em> macro initializes the list with the arguments <code>arg_list<\/code> and <code>a<\/code>, which is the argument count.<\/p>\n<p>The values passed are fetched the <em>for<\/em> loop at line 13. Each value is represented by the <em>va_arg()<\/em> macro. Its two arguments are <code>arg_list<\/code> (the <em>va_list<\/em> variable) and the variable&#8217;s expected data type. For this code, the values are all integers so <em>int<\/em> is specified.<\/p>\n<p>After the variable list arguments are output, the <em>va_end()<\/em> macro at Line 19 wraps up the action. Its argument is the <code>arg_list<\/code> variable.<\/p>\n<p>It&#8217;s possible to pass different data types in the variable argument list. The <em>va_arg()<\/em> macro must set the proper data type, therefore the argument order is important. Or, in the case of the <em>printf()<\/em> function, the arguments types are stipulated in the format string, so a <em>switch-case<\/em> structure parses the options using the proper data types in a cascade of <em>va_arg()<\/em> functions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Understand how functions such as <em>printf()<\/em> lack a specific list of arguments. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3398\">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-3398","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\/3398","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=3398"}],"version-history":[{"count":4,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3398\/revisions"}],"predecessor-version":[{"id":3419,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/3398\/revisions\/3419"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}