    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Compile Time Assertions in C Revisited</title>
        <link>https://members.accu.org/index.php/journals/907</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 11, #5 - Aug 1999 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c130/">115</a>
                    (21)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c130-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c130+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Compile Time Assertions in C Revisited</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 August 1999 13:15:32 +01:00 or Tue, 03 August 1999 13:15:32 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
</div>
<p>I am pleased that my article on compile time assertions has
provoked some feedback. To start off I'll paste in the final code
from my C Vu 11.3 article.</p>
<pre class="programlisting">
#include &lt;limits.h&gt;

#define COMPILE_TIME_ASSERT(pred)       switch(0){case 0:case pred:;}

#define ASSERT_MIN_BITSIZE(type,size)        \
COMPILE_TIME_ASSERT(sizeof(type) * CHAR_BIT &gt;= size)

#define ASSERT_EXACT_BITSIZE(type,size)       \
  COMPILE_TIME_ASSERT(sizeof(type) * CHAR_BIT == size)
void compile_time_assertions(void) {
  ASSERT_MIN_BITSIZE(char,  8);
  ASSERT_MIN_BITSIZE(int,  16);
  ASSERT_EXACT_BITSIZE(long, 32);
}
</pre>
<p>A number of readers criticised the above code. Too complicated
they cried. There are two ways to interpret such remarks. The first
is that the technique in general is too complicated. I have a lot
of sympathy with this point of view. C was not designed with
compile time assertions in mind. You might reject compile time
assertions altogether and opt for a more conventional runtime
solution. As Kevlin Henney pointed out in his letter to the editor
(C Vu 11.4), pre-processor based compilation errors are, to say the
least, less than helpful.</p>
<p>The second interpretation is that the technique is too
complicated and there are simpler techniques for implementing
compile time assertions. Strange as it may seem I also have a lot
of sympathy for this view. Again, whichever way you try to skin it,
this particular cat is tricky. C was not designed with compile time
assertions in mind. Compile time assertions are right on the edge -
it's highly likely that individual preferences will come into play.
However, I stand by my implementation of compile time assertions as
presented above. Well, almost. If ever a piece of code cried out
for a comment, this is it. But let me be specific: I do not think
that the function <tt class="function">compile_time_assert</tt>
needs any comments (although in hindsight I think <tt class=
"function">type_size_constraints</tt> would be a better name). Nor
do I think that the <tt class="function">ASSERT_MIN_BITSIZE</tt>
macro needs a comment. <tt class=
"function">ASSERT_EXACT_BITSIZE</tt> is fine as it stands too,
imho. No, the comment is needed for the <tt class=
"function">COMPILE_TIME_ASSERT</tt> macro. This is decidedly not
obvious. What should the comment for <tt class=
"function">COMPILE_TIME_ASSERT</tt> say? The text of the previous
article would be a good place to start.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e48" id="d0e48"></a>Arithmetic in
the Preprocessor?</h2>
</div>
<p>In C Vu 11.4 Silas suggested an alternative technique for
asserting a compile time requirement.</p>
<pre class="programlisting">
#include &lt;limits.h&gt;
#if CHAR_BIT &lt; 8
#error This program assumes a compiler that supports 8-bit chars
#endif

#define byte1(c)     ((c) &amp; 0xFF)
#define byte2(c)     byte1((c) &gt;&gt; 8)
#define byte3up(c)   ((c) &gt;&gt; 16)
#define TwoByteFail(c,min2,min1)  \
        (!byte3up(c) &amp;&amp; byte2(c) &lt; min2 || byte2c) &lt; min1)

#if TwoByteFail(USHRT_MAX, 0xFF, 0xFF)
#error This program assumes a compiler that supports 16-bit shorts
#endif
</pre>
<p>I assume that Silas meant to write <tt class="literal">#if
CHAR_BIT != 8</tt>. If <tt class="literal">CHAR_BIT</tt> is less
than eight than your compiler is non-conforming!<sup>[<a name=
"d0e63" href="#ftn.d0e63" id="d0e63">1</a>]</sup> The C standard
states that <tt class="literal">CHAR_BIT</tt> is an expression
(usable in a <tt class="literal">#if</tt> directive) that is
greater than or equal to eight. There is also the style issue that
function macros are conventionally uppercase.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e75" id="d0e75"></a>Here be
dragons</h2>
</div>
<p>The fundamental problem, as I see it, with this approach is that
it uses constant-expressions in a <tt class="literal">#if</tt>
directive. This raises a question: what are the types of the
constants used in the constant-expressions? This matters because
there are shift operators. If <tt class="literal">USHRT_MAX</tt> is
an unsigned integer then the right-shift will introduce 0's in the
most-significant bit. If <tt class="literal">USHRT_MAX</tt> is a
signed integer then the right-shift might introduce 1's in the
most-significant bit.<sup>[<a name="d0e89" href="#ftn.d0e89" id=
"d0e89">2</a>]</sup></p>
<p>The type of a literal constant will depend on the platform. For
<tt class="type">unsigned short</tt> for example, the effect of the
promotion rules is to favour promoting to <tt class="type">int</tt>
wherever possible, but to promote to <tt class="type">unsigned
int</tt> if necessary to preserve the original value in all
possible cases. This is bad news because the macros are designed to
test type sizes.</p>
<p>But hang on. The promotion rules of C are the promotion rules of
C. The preprocessor is not C. Look carefully at the C standard and
you'll find that inside a <tt class="literal">#if</tt> directive
the promotion rules are different! The pre-processor is obliged to
promote to <tt class="type">long</tt> instead of <tt class=
"type">int</tt> and to <tt class="type">unsigned long</tt> instead
of <tt class="type">unsigned int</tt>. It's highly likely that the
type of <tt class="literal">USHRT_MAX</tt> will be a <tt class=
"type">signed long</tt>.</p>
<p>And it's potentially even worse than that!! If you're cross
compiling the pre-processor won't even be running on the target
computer. For all these reasons I think a solution that avoids
<tt class="literal">#if</tt> directives is well-advised.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e140" id="d0e140"></a>Do it
yourself</h2>
</div>
<p>To return to Kevlin's letter for a moment. He writes
&quot;pre-processor symbols lose their identity in the process of
compilation, which leads to succinct but useless messages...&quot; Can
compile time assertions be achieved without the pre-processor? Of
course - do the expansion yourself.</p>
<pre class="programlisting">
#include &lt;limits.h&gt;

void type_size_constraints(void) {
  switch(0){case 0: case CHAR_BIT == 8:;}
  switch(0){case 0: case sizeof(int)*CHAR_BIT &gt;= 16:;}
  switch(0){case 0: case sizeof(long)*CHAR_BIT == 32:;}
}
</pre>
<p>With the compile time mechanism out in the open the game has
changed slightly. There's a lot to be said for using one of the
other techniques. For example</p>
<pre class="programlisting">
#include &lt;limits.h&gt;
char require_char_exactly_8_bits[CHAR_BIT == 8];
char require_int_at_least_16_bits[sizeof(int)  * CHAR_BIT &gt;= 16];
char require_long_exactly_32_bits[sizeof(long) * CHAR_BIT == 32];
</pre>
<p>This does not require an enclosing function. We can name the
arrays to document the constraint. Each array will only be a single
character long. There's a good chance we'll get fewer compiler
warnings (than the switch solution). And we won't be affected by
the changes proposed in the new C standard (which Francis hinted at
in his editor's comment). It occurs to me that we can test the type
sizes in terms of bytes rather than bits. For example</p>
<pre class="programlisting">
#include &lt;limits.h&gt;
char require_8_bit_byte[CHAR_BIT == 8];
char require_2_byte_int[sizeof(int) == 2]; 
char require_4_byte_long[sizeof(long) == 4];
</pre>
<p>These are all definitions. You would not be able to put them in
a header file. To do that we need declarations. There are a number
of possibilities.</p>
<pre class="programlisting">
#include &lt;limits.h&gt;
/* 1. extern array declaration */
extern char require_8_bit_byte[CHAR_BIT == 8];
/* 2. function prototype with array parameter */
void require_8_bit_byte(char[CHAR_BIT == 8]);
/* 3. array typedef */
typedef char require_8_bit_byte[CHAR_BIT == 8];
/* 4. struct with array member */
struct type_size_constraints {
    char require_8_bit_byte[CHAR_BIT == 8];
    char require_2_byte_int[sizeof(int) == 2];
    char require_4_byte_long[sizeof(long) == 4];
};
</pre>
<p>The last approach has the benefit of providing a grouping
mechanism for all compile time constraints in a file. However, this
might fall foul of compilers extended to allow zero sized arrays as
a last struct member. To get round this we can provide a dummy last
member.</p>
<pre class="programlisting">
struct type_size_constraints {
    char require_8_bit_byte [CHAR_BIT == 8];
    char require_2_byte_int [sizeof(int) == 2];
    char require_4_byte_long[sizeof(long) == 4];
    char non_empty_dummy_last_member[1];
};
</pre>
<p>This seems to be getting close to a distilled essence. Still
with a chunky comment of course.</p>
<p>Thanks to Kevlin for advice and comments.</p>
<p>That's all for now</p>
<p>Cheers</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e171" id=
"d0e171"></a>Bibliography</h2>
</div>
<div class="bibliomixed">
<p class="bibliomixed">Quote from Gerald Weinberg in The Psychology
of Computer Programming. &quot;The programming business relies more than
any other on unending learning&quot;.</p>
</div>
</div>
<div class="footnotes"><br>
<hr class="c2" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e63" href="#d0e63" id=
"ftn.d0e63">1</a>]</sup> There was a superfluous assertion in the
previous article...</p>
<pre class="programlisting">
  ASSERT_MIN_SIZE(char,8);
</pre></div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e89" href="#d0e89" id=
"ftn.d0e89">2</a>]</sup> Notice that <tt class=
"literal">USHRT_MAX</tt> cannot be a literal of type short. There
is the L suffix for long literals but there is no S suffix for
short literals, presumably because of the default short-to-int
promotion in K&amp;R C. Notice also, in <tt class="literal">E1
&gt;&gt; E2</tt>, if <tt class="literal">E1</tt> has a signed type
and a negative value, the resulting value is
implementation-defined.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
