{"id":442,"date":"2009-10-16T00:04:09","date_gmt":"2009-10-16T05:04:09","guid":{"rendered":"http:\/\/vgable.com\/blog\/?p=442"},"modified":"2009-10-16T12:42:10","modified_gmt":"2009-10-16T17:42:10","slug":"hack-counting-varadic-arguments-in-c","status":"publish","type":"post","link":"https:\/\/vgable.com\/blog\/2009\/10\/16\/hack-counting-varadic-arguments-in-c\/","title":{"rendered":"Hack: Counting Variadic Arguments in C"},"content":{"rendered":"<p>This isn&#8217;t practical, but I think it&#8217;s neat that it&#8217;s doable in C99. The implementation I present here is <strong>incomplete and for illustrative purposes only<\/strong>.<\/p>\n<h3>Background<\/h3>\n<p>C&#8217;s implementation of <a href=\"http:\/\/cocoawithlove.com\/2009\/05\/variable-argument-lists-in-cocoa.html\">variadic functions<\/a> (functions that take a variable-number of arguments) is characteristically bare-bones. Even though the compiler knows the number, and type, of all arguments  passed to variadic functions; there isn&#8217;t a mechanism for the function to get this information from the compiler. Instead, programmers need to pass an extra argument, like the <code>printf<\/code> <a href=\"http:\/\/en.wikipedia.org\/wiki\/Printf#printf_format_placeholders\">format-string<\/a>, to tell the function &#8220;these are the arguments I gave you&#8221;. This has worked for over 37 years. But it&#8217;s clunky &#8212; you have to write the same information twice, once for the compiler and again to tell the function what you told the compiler.<\/p>\n<h3>Inspecting Arguments in C<\/h3>\n<h4>Argument Type<\/h4>\n<p><strong>I don&#8217;t know of a way to find the type of the Nth argument to a varadic function, called with heterogeneous types.<\/strong> If you can figure out a way, I&#8217;d love to know. <strong>The <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/gcc\/Typeof.html\"><code>typeof<\/code><\/a> extension is often sufficient to write generic code that works when every argument has the same type.<\/strong> (<a href=\"http:\/\/www.cplusplus.com\/doc\/tutorial\/templates\/\">C++ templates<\/a> also solve this problem if we step outside of C-proper.)<\/p>\n<h4>Argument Count (The Good Stuff Starts Here)<\/h4>\n<p><strong>By using <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Variadic-Macros.html\">variadic macros<\/a>, and <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Stringification.html\">stringification (<code>#<\/code>)<\/a>, we can actually pass a function the literal string of its argument list from the source code &#8212; which it can parse to determine how many arguments it was given.<br \/>\n<\/strong><\/p>\n<p>For example, say <code>f()<\/code> is a variadic function. We create a variadic wrapper macro, <code>F()<\/code> and call it like so in our source code,<\/p>\n<pre>x = F(a,b,c);<\/pre>\n<p>The preprocessor expands this to,<\/p>\n<pre>x = f(\"a,b,c\",a,b,c)<\/pre>\n<p>Or perhaps,<\/p>\n<pre>x = f(count_arguments(\"a,b,c\"),a,b,c)<\/pre>\n<p>where <code>count_arguments(char *s)<\/code> returns the number of arguments in the string source-code string <code>s<\/code>. (Technically <code>s<\/code> would be an argument-expression-list).<\/p>\n<h3>Example Code<\/h3>\n<p>Here&#8217;s an implementation for, <code>iArray()<\/code>, an array-builder for <code>int<\/code> values, very much like <a href=\"http:\/\/www.amazon.com\/gp\/product\/0596101996?ie=UTF8&#038;tag=vincgabl-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0596101996\">JavaScript<\/a>&#8216;s <code>Array()<\/code> constructor. Unlike the <a href=\"http:\/\/www.youtube.com\/watch?v=hQVTIJBZook\">quirky JavaScript<\/a> <code>Array()<\/code>, <code>iArray(3)<\/code> returns an array containing just the element 3, <code>[3]<\/code>, not an uninitilized array with 3 elements, <code>[undefined, undefined, undefined]<\/code>. Another difference: <code>iArray()<\/code>, invoked with no arguments, is invalid, and will not compile.<\/p>\n<pre>\n#define iArray(...) alloc_ints(count_arguments(#__VA_ARGS__), __VA_ARGS__)\n<\/pre>\n<p>This macro is pretty straightforward. It&#8217;s given a variable number of arguments, represented by <code>__VA_ARGS__<\/code> in the expansion. <code>#__VA_ARGS__<\/code> <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Stringification.html\">turns the code into a string<\/a> so that <code>count_arguments<\/code> can analyze it. (If you were doing this for real, you should use two levels of <a href=\"http:\/\/gcc.gnu.org\/onlinedocs\/cpp\/Stringification.html\">stringification<\/a> though, otherwise macros won&#8217;t be fully expanded. I choose to keep things &#8220;demo-simple&#8221; here.)<\/p>\n<pre>\nunsigned count_arguments(char *s){\n\tunsigned i,argc = 1;\n\t\tfor(i = 0; s[i]; i++)\n\t\t\tif(s[i] == ',')\n\t\t\t\targc++;\n\treturn argc;\n}\n<\/pre>\n<p>This is a <strong>dangerously naive<\/strong> implementation and only works correctly when <code>iArray()<\/code> is given a straightforward non-empty list of values or variables. Basically it&#8217;s the least code I could write to make a working demo.<\/p>\n<p>Since <code>iArray<\/code> must have at least one argument to compile, we just count the commas in the argument-list to see how many other arguments were passed. Simple to code, but it fails for more complex expressions like <code>f(a,g(b,c))<\/code>.<\/p>\n<pre>\nint *alloc_ints(unsigned count, ...){\n\tunsigned i = 0;\n\tint *ints = malloc(sizeof(int) * count);\n\tva_list args;\n    va_start(args, count);\n\tfor(i = 0; i < count; i++)\n\t\tints[i] = va_arg(args,int);\n\tva_end(args);\n\treturn ints;\n}\n<\/pre>\n<p>Just as you'd expect, this code allocates enough memory to hold <code>count<\/code> <code>int<\/code>s, and fills it with the remaining <code>count<\/code> arguments. Bad things happen if &lt; <code>count<\/code> arguments are passed, or they are the wrong type.<\/p>\n<p><a href=\"http:\/\/vgable.com\/code\/iArray.c\">Download the code<\/a>, if you like.<\/p>\n<h3><a href=\"http:\/\/steve-yegge.blogspot.com\/2007\/06\/rich-programmer-food.html\">Parsing is Hard<\/a>, Let's Go Shopping<\/h3>\n<p>I didn't even try to correctly parse <em>any<\/em> valid argument-expression-list in <code>count_arguments<\/code>. It's non trivial. I'd rather deal with choosing the correct <code>MAX3<\/code> or <code>MAX4<\/code> macro in a few places than maintain such a code base.<\/p>\n<p>So this kind of introspection isn't really practical in C. But it's neat that it can be done, without any tinkering with the compiler or language.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This isn&#8217;t practical, but I think it&#8217;s neat that it&#8217;s doable in C99. The implementation I present here is incomplete and for illustrative purposes only. Background C&#8217;s implementation of variadic functions (functions that take a variable-number of arguments) is characteristically bare-bones. Even though the compiler knows the number, and type, of all arguments passed to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,4,11,13,8],"tags":[613,504,505,417,503,502],"class_list":["post-442","post","type-post","status-publish","format-standard","hentry","category-design","category-programming","category-research","category-sample-code","category-usability","tag-c","tag-introspection","tag-parsing","tag-programming-language-design","tag-variadic-functions","tag-variadic-macros"],"_links":{"self":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/442","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/comments?post=442"}],"version-history":[{"count":9,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/442\/revisions"}],"predecessor-version":[{"id":455,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/posts\/442\/revisions\/455"}],"wp:attachment":[{"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/media?parent=442"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/categories?post=442"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vgable.com\/blog\/wp-json\/wp\/v2\/tags?post=442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}