Principles for C programming
<i>Avoid magic. Do not use macros.</i><p>Disagree.  Use magic, especially macros, <i>in ways such that your code becomes easier, not harder, to understand</i>.<p>A few examples from my own code:<p>1. My &quot;elastic arrays&quot; (<a href="https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;master&#x2F;datastruct&#x2F;elasticarray.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;master&#x2F;datastruc...</a> and .c) allow me to write<p><pre><code>    ELASTICARRAY_DECL(STRLIST, strlist, const char *);
</code></pre>
and get a data structure STRLIST which contains an arbitrary number of strings and functions strlist_init, strlist_append, strlist_get, strlist_free, etc. for accessing the array.  Compared to the non-macro approach of keeping track of the array size and resizing as needed, this makes code vastly simpler.  (Of course, this sort of data structure is built into most non-C languages already.)<p>2. My &quot;magic getopt&quot; (<a href="https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;commit&#x2F;53d00e5bd0478fcc89bc056d192a476fb89277a4" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;commit&#x2F;53d00e5bd0478f...</a>) allows me to something which looks and behaves just like a standard UNIX getopt loop, except with support for --long options.  Yes, the implementation is mildly insane (and needs to work around a bug in clang!), but it allows for code which is vastly simpler than other getopt-with-long-options alternatives.<p>3. My &quot;cpu features support&quot; framework (<a href="https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;master&#x2F;cpusupport&#x2F;cpusupport.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;master&#x2F;cpusuppor...</a>) makes use of both macros and some tricky edge cases of C object linkage rules, but makes it trivial for me to add support for new CPU features.<p>4. Soon to be released, the PARSENUM macro (WIP: <a href="https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;parsenum-additions&#x2F;util&#x2F;parsenum.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Tarsnap&#x2F;libcperciva&#x2F;blob&#x2F;parsenum-additio...</a>) which allows me to write<p><pre><code>    PARSENUM(&amp;n, &quot;1234&quot;);
    PARSENUM(&amp;x, &quot;123.456&quot;);
    PARSENUM(&amp;s, &quot;123&quot;, 0, 1000);
</code></pre>
where the first argument is a pointer to a variable of any integer or floating-point type to which is assigned the numeric value of the string in the second argument; for floating-point values and unsigned integers, the two-argument form range-checks the value against the bounds of the type, while the four-argument form range-checks against the provided bounds.  (Basically, this is strtonum on steroids.)<p>In all of these cases, <i>you will never need to understand how these macros work</i>.  Instead, you can simply treat them as language extensions which allow you to write cleaner and simpler code.