<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>mikeash.com pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html comments</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>mikeash.com Recent Comments</description><lastBuildDate>Sun, 10 May 2026 05:05:29 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>mikeash - 2009-10-28 15:04:49</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Definitely not missing a comma. Imagine this usage of the macro:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;DEBUG_LOG("the answer is %d", fortyTwo);&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;With the comma, the line would expand to:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;fprintf(stderr, "Debug log:", "the answer is %d", fortyTwo);&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;With the result that it will print only the text, "Debug log:", and nothing else.
&lt;br /&gt;
&lt;br /&gt;Without the comma, it expands to this:
&lt;br /&gt;
&lt;br /&gt;&lt;code&gt;fprintf(stderr, "Debug log:" "the answer is %d", fortyTwo);&lt;/code&gt;
&lt;br /&gt;
&lt;br /&gt;The adjacent string literals get concatenated, and so it prints, "Debug log:the answer is 42".
&lt;br /&gt;
&lt;br /&gt;It ought to have a space after the colon, though....</description><guid isPermaLink="true">24fe5c2efa0e1db3b7960714698eaf9c</guid><pubDate>Wed, 28 Oct 2009 15:04:49 GMT</pubDate></item><item><title>Jeanne d'Arc - 2009-10-28 10:41:28</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>There's probably a missing ',' here:
&lt;br /&gt;
&lt;br /&gt;fprintf(stderr, "Debug log:" __VA_ARGS__); \</description><guid isPermaLink="true">a65dd339f860523b6530e9a2c7ed9e8f</guid><pubDate>Wed, 28 Oct 2009 10:41:28 GMT</pubDate></item><item><title>mikeash - 2009-08-25 14:07:38</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>It's likely that clang supports such devices as well. Their stated goal is to support nearly all gcc language extensions so that clang is able to build nearly all existing gcc-targeted code.
&lt;br /&gt;
&lt;br /&gt;Your ARRAY macro ought to work for empty arrays as well, but you have to pass an explicit nil parameter instead of just leaving the list empty. If you really wanted to you could pair it with a custom vararg function/method that allowed an empty parameter list in the macro.</description><guid isPermaLink="true">1dcd9b21fca02d5bbd9445de3387745a</guid><pubDate>Tue, 25 Aug 2009 14:07:38 GMT</pubDate></item><item><title>Vasi - 2009-08-25 07:31:09</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>A drawback of using do/while is that your macro can't return a value. (I also find do/while in macros aesthetically unpleasant, but that's just me.) An alternative is to use GCC's multi-statement expressions: &lt;a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Statement-Exprs.html#Statement-Exprs"&gt;http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Statement-Exprs.html#Statement-Exprs&lt;/a&gt; . This lets you do things like:
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;
&lt;br /&gt;#define ARRAY_DEBUG(...) ({
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NSArray *_a = [NSArray arrayWithObjects: __VA_ARGS__];
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (gDebug)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dumpArray(_a);
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_a;
&lt;br /&gt;})
&lt;br /&gt;
&lt;br /&gt;...
&lt;br /&gt;
&lt;br /&gt;NSArray *myArray = ARRAY_DEBUG(@"foo", @"bar", nil);
&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;The downside is of course that this is non-portable. I have no idea whether or not clang supports this extension.
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;On a different note, one very common use for vararg macros is to abbreviate nil-terminated vararg functions. Eg:
&lt;br /&gt;
&lt;br /&gt;&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;
&lt;br /&gt;#define ARRAY(...) [NSArray arrayWithObjects: __VA_ARGS__, nil]
&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;This has the drawback of not working for empty arrays, but there are easier ways to create those. Jens Alfke's utilities may be better &lt;a href="https://bitbucket.org/snej/myutilities/src/tip/CollectionUtils.h"&gt;https://bitbucket.org/snej/myutilities/src/tip/CollectionUtils.h&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">6b0112967c4da22490bab174f9ce5620</guid><pubDate>Tue, 25 Aug 2009 07:31:09 GMT</pubDate></item><item><title>mikeash - 2009-08-24 15:41:27</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Heh. Whoops. Thanks Peter! I've fixed all three now.</description><guid isPermaLink="true">e14fa5ef3121ff4159f316307687bda7</guid><pubDate>Mon, 24 Aug 2009 15:41:27 GMT</pubDate></item><item><title>Peter N Lewis - 2009-08-24 14:01:38</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Regardless of whether the DEBUG_LOG uses { } or do while, it really should have an equal number of opening and closing currly brackets.
&lt;br /&gt;
&lt;br /&gt;It is also definitely worth mentioning the NS_REQUIRES_NIL_TERMINATION macro!
&lt;br /&gt;</description><guid isPermaLink="true">7858b3a2fbb0c623fdae5ade96f150d9</guid><pubDate>Mon, 24 Aug 2009 14:01:38 GMT</pubDate></item><item><title>gabe - 2009-08-23 09:24:24</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Some more detail on multi statement macros from comp.lang.c faq, &lt;a href="http://c-faq.com/cpp/multistmt.html"&gt;http://c-faq.com/cpp/multistmt.html&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">319c2a2f3266b0eebf835f90594290f4</guid><pubDate>Sun, 23 Aug 2009 09:24:24 GMT</pubDate></item><item><title>mikeash - 2009-08-22 23:06:44</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Regardless of the actual calling conventions, you should never write code that calls functions without prototypes. Aside from being non-conforming code even if it does happen to work on your particular platform, it's also all too easy to screw up your types. For example, it is impossible to correctly call a function which takes a float parameter in this way, because a float passed to a prototype-less function will always be promoted to double. It's also easy to accidentally pass 0 instead of 0.0, which would normally cause a harmless implicit conversion but in the absence of a prototype will screw you over hard.</description><guid isPermaLink="true">8709f47dee0bf723211e3a78e6c06fa9</guid><pubDate>Sat, 22 Aug 2009 23:06:44 GMT</pubDate></item><item><title>Jean-Daniel Dupas - 2009-08-22 22:31:59</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>&lt;div class="blogcommentquote"&gt;&lt;div class="blogcommentquoteinner"&gt;In particular, on platforms that use registers to pass arguments they tend to shove all of the args into GPRs even though the standard calling convention might have you place singles and doubles in FPRs&lt;/div&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;That not quite true. See for example on PPC:
&lt;br /&gt;
&lt;br /&gt;printf("%f", 10.0);
&lt;br /&gt;
&lt;br /&gt;Generate this assembly:
&lt;br /&gt;=&amp;gt;  fmr f1,f0
&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bl _fprintf$LDBL128
&lt;br /&gt;
&lt;br /&gt;And it uses mmx register on x86_64.
&lt;br /&gt;
&lt;br /&gt;So you can see that even on arch that uses register to pass argument, floating point register are use to pass floating point values. 
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">f109b654765abdbcbf5e9ccb7994cb0c</guid><pubDate>Sat, 22 Aug 2009 22:31:59 GMT</pubDate></item><item><title>Louis Gerbarg - 2009-08-22 19:41:38</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>It might be worth mentioning that on a number of architectures variadic functions have substantially different calling conventions that non-variadic functions. In particular, on platforms that use registers to pass arguments they tend to shove all of the args into GPRs even though the standard calling convention might have you place singles and doubles in FPRs, since the compiler doesn't have any type info for the va_args.
&lt;br /&gt;
&lt;br /&gt;This manifests itself in several ways. The first is slightly less efficient code (copying stuff back and forth from fprs to gprs, or extra copies to the stack), the second is that if you ignore missing prototype warnings (everyone compiles with -Wall=error, right) you may get code that links correctly but crashes because the calling function doesn't put things where the called function expects them.</description><guid isPermaLink="true">445cb2f3c5ac5f2d1ba214f0466d8e3d</guid><pubDate>Sat, 22 Aug 2009 19:41:38 GMT</pubDate></item><item><title>Jonas Witt - 2009-08-22 01:30:50</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Ok, so you were referring to the semicolon which is required after the do/while but won't work after the { } block. Thanks for the explanation.</description><guid isPermaLink="true">6d81fe157aa0128bb660ff13b7257a9e</guid><pubDate>Sat, 22 Aug 2009 01:30:50 GMT</pubDate></item><item><title>mikeash - 2009-08-22 01:07:54</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>No, curly braces do &lt;i&gt;not&lt;/i&gt; achieve the same effect. Go look at my example if/else code and consider what happens if you use your style in there. It will not compile.</description><guid isPermaLink="true">73f2b32a65933179b2fa47b4805ee9e0</guid><pubDate>Sat, 22 Aug 2009 01:07:54 GMT</pubDate></item><item><title>Cedric Luthi - 2009-08-22 00:42:55</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>A nice complement to this article: Variable argument lists in Cocoa
&lt;br /&gt;&lt;a href="http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html"&gt;http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html&lt;/a&gt;
&lt;br /&gt;
&lt;br /&gt;Worth a read.</description><guid isPermaLink="true">96b4a941cfcfae82b58b60c983ab0fbb</guid><pubDate>Sat, 22 Aug 2009 00:42:55 GMT</pubDate></item><item><title>Jonas Witt - 2009-08-22 00:35:36</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>You say that using do/while(0) is a great way to put multiple statements in a macro (if you don't want it to fail in places where a single statement is expected), but the same can be achieved simply by using a pair of curly braces (which you use for while anyway since while expects a single statement/block) to create a new scope/block:
&lt;br /&gt;
&lt;br /&gt;#define FOO { method1(); method2(); }
&lt;br /&gt;
&lt;br /&gt;IMO this is idential to the while construct in every aspect (variable scope, ...).
&lt;br /&gt;
&lt;br /&gt;</description><guid isPermaLink="true">0ed2f551b3e49708158e3f4aaa523e53</guid><pubDate>Sat, 22 Aug 2009 00:35:36 GMT</pubDate></item><item><title>mikeash - 2009-08-22 00:30:46</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>I actually discuss the 0 problem, in a slightly different context, in the Beware of NULL section of Format Strings Tips and Tricks from a month ago:
&lt;br /&gt;
&lt;br /&gt;&lt;a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-07-17-format-strings-tips-and-tricks.html"&gt;http://www.mikeash.com/?page=pyblog/friday-qa-2009-07-17-format-strings-tips-and-tricks.html&lt;/a&gt;</description><guid isPermaLink="true">85d2fe709230d7d399be4fd9eb6eb190</guid><pubDate>Sat, 22 Aug 2009 00:30:46 GMT</pubDate></item><item><title>Chris - 2009-08-22 00:10:24</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Another omission is the "gotcha" related to (IIRC) argument promotion and callers passing an integer 0 instead of a zero *pointer* to terminate the argument list.
&lt;br /&gt;
&lt;br /&gt;This causes problems (again, IIRC) on 64-bit systems.</description><guid isPermaLink="true">1707c16d72731b351635ac674fd483d5</guid><pubDate>Sat, 22 Aug 2009 00:10:24 GMT</pubDate></item><item><title>Jordy/Jediknil - 2009-08-21 23:59:28</title><link>http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-21-writing-vararg-macros-and-functions.html#comments</link><description>Very convenient, but you left out the most confusing one: vararg methods!
&lt;br /&gt;
&lt;br /&gt;Like vararg functions, vararg methods require at least one fixed parameter. The va_list/va_start/va_arg API is the same. And they are declared like this:
&lt;br /&gt;
&lt;br /&gt;- (NSString *)stringByAppendingStrings:(NSString *)first, ...;
&lt;br /&gt;
&lt;br /&gt;And the restriction of one fixed argument is a lot more arbitrary here, because, as we well know, an Objective-C method is passed two hidden arguments (self and _cmd). In theory I would expect va_start(_cmd) to work, but I wouldn't use it in practice, especially given potential compiler differences in this field!
&lt;br /&gt;
&lt;br /&gt;Finally, there's a nice macro called NS_REQUIRES_NIL_TERMINATION that expands to a GCC __attribute__ ((sentinel)), which will warn when any invocations of the function aren't nil-terminated (if you have -Wformat turned on). This works for both functions and methods.</description><guid isPermaLink="true">78653f018a7685adcd4388734c17cbd7</guid><pubDate>Fri, 21 Aug 2009 23:59:28 GMT</pubDate></item></channel></rss>
