    <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  :: Code Critique Competition 94</title>
        <link>https://members.accu.org/index.php/articles/2124</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>




<div class="xar-mod-head"><span class="xar-mod-title">Student Code Critiques from CVu journal. + CVu Journal Vol 27, #3 - July 2015</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/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c184/">Journal Columns</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c183/">Code Critique</a>
<br />

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

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

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

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c351/">273</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c183-351/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c183+351/">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;Code Critique Competition 94</h1>
<p><strong>Author:</strong>&nbsp;Martin Moene</p>
<p>
<strong>Date:</strong> 05 July 2015 21:56:30 +01:00 or Sun, 05 July 2015 21:56:30 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Set and collated by Roger Orr. A book prize is awarded for the best entry.</p>
<p><strong>Body:</strong>&nbsp;<p class="EditorIntro">Participation in this competition is open to all members, whether novice or expert. Readers are also encouraged to comment on published entries, and to supply their own possible code samples for the competition (in any common programming language) to scc@accu.org.</p>

<p class="EditorIntro">Note: If you would rather not have your critique visible online, please inform me. (We will remove email addresses!)</p>

<h2>Last issueâ€™s code</h2>

<p class="blockquote">Iâ€™m trying to write a simple program to demonstrate the Mandelbrot set and Iâ€™m hoping to get example output like this Figure 1, but I just get 6 lines of stars and the rest blank. Can you help me get this program working?</p>
<p>Can you find out what is wrong and help this programmer to fix (and improve) their simple test program? The code is in Listing 1.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
                                      *
                                    ****
                                    ****
                                    ****

                              *  **********
                             ******************
                              *****************
                             *****************
                            *******************
                           **********************
                           *********************
                 * **     **********************
                 *******  **********************
                ********* **********************
                ********* **********************
              * ********* *********************
 *********************************************
              * ********* *********************
                ********* **********************
                ********* **********************
                 *******  **********************
                 * **     **********************
                           *********************
                           **********************
                            *******************
                             *****************
                              *****************
                             ******************
                              *  **********

                                    ****
                                    ****
                                    ****
                                      *
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Figure 1</td>
	</tr>
</table>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
#include &lt;array&gt;
#include &lt;complex&gt;
#include &lt;iostream&gt;
using row = std::array&lt;bool, 60&gt;;
using matrix = std::array&lt;row, 40&gt;;
std::ostream&amp; operator&lt;&lt;(std::ostream &amp;os, 
  row const &amp;rhs)
{
  for (auto const &amp;v : rhs)
    os &lt;&lt; &quot;* &quot;[v];
  return os;
}
std::ostream&amp; operator&lt;&lt;(std::ostream &amp;os, 
  matrix const &amp;rhs)
{
  for (auto const &amp;v : rhs)
    os &lt;&lt; v &lt;&lt; '\n';
  return os;  
}

class Mandelbrot
{
  matrix data = {};
  std::complex&lt;double&gt; origin = (-0.5);
  double scale = 20.0;
public:
  matrix const &amp; operator()()
  {
    for (int y(0); y != data.size(); ++y)
    {
      for (int x(0); x != data[y].size(); ++x)
      {
        std::complex&lt;double&gt;
          c = (xcoord(x), ycoord(y)), z = c;
        int k = 0;
        for (; k &lt; 200; ++k)
        {
          z = z*z + c;
          if (abs(z) &gt;= 2)
          {
            data[y][x] = true;
            break;
          }
        }
      }
    }
    return data;
  }
private:
  double xcoord(int xpos)
  {
     return origin.real() + (xpos -
       data[0].size()/2) / scale;
  }
  double ycoord(int ypos)
  {
     return origin.imag() + (data.size()/2 -
       ypos) / scale;
  }
};
int main()
{
  Mandelbrot set;
  std::cout &lt;&lt; set() &lt;&lt; std::endl;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<h2>Critiques</h2>

<h3>Paul Floyd</h3>

<p>It took some debugging to get to the causes of the errors.</p>

<p>First impressions. I didnâ€™t like the uncommented use of indexing a string literal in the row <code>operator&lt;&lt;</code>. I understood it, but not all developers would. As itâ€™s a relatively rare idiom, it needs an explanatory comment. Just to make sure that there was no problem with the output, I changed the literal to <code>*.</code> so that the â€˜trueâ€™ values printed something more visible. And indeed there was no problem there. I had a quick check that the unqualified call to <code>abs</code> was indeed calling the complex version rather than the <code>int</code> one. Lastly I didnâ€™t like the gratuitous use of <code>operator()</code>, defined in the class body to boot. Iâ€™d prefer a named function like <code>calculate</code>. If <code>calculate</code> is always called after construction, then Iâ€™d call it from the constructor instead.</p>

<p>Next, compiling the code. I tried with</p>

<ul>
	<li>Solaris Studio 12.4 â€“ no warnings</li>
	
	<li>clang++ 3.2 â€“ complained about sign comparison in the <code>x</code> and <code>y</code> for loops</li>
	
	<li>g++ 4.8.2 â€“ same <code>x</code> and <code>y</code> for loop sign comparison, and also about missing field initializers for <code>Mandelbrot::data</code>.</li>
</ul>

<p>So I started adding some debug traces. I noticed fairly quickly that the values of complex <code>c</code> and <code>z</code> always had zero imaginary parts. I looked at initializer expression for <code>c</code></p>

<pre class="programlisting">
  std::complex&lt;double&gt; c = (xcoord(x), ycoord(y));</pre>

<p>and saw the first light. That doesnâ€™t initialize a <code>std::complex</code> with two fields. Itâ€™s an operator, expression in parentheses. The result of the expression is a double, and thereâ€™s a <code>std::complex</code> constructor overload that takes just a double, so it can be converted to <code>std::complex</code>.</p>

<p>In C++11 uniform initialization style, this should be</p>

<pre class="programlisting">
  std::complex&lt;double&gt; c = {xcoord(x), ycoord(y)};</pre>

<p>The next thing that I noticed were some excessively high values coming from <code>xcoord(x)</code>. These looked suspiciously like <code>INT_MAX</code>. I added traces for all of the values used in <code>xcoord()</code>, and they all looked reasonable.</p>

<p>Then I looked a bit more closely at the expression:</p>

<pre class="programlisting">
  return origin.real() + (xpos - 
    data[0].size()/2) / scale;</pre>
	
<p>In terms of types, that is</p>

<pre class="programlisting">
  double + (int - size_t/int) / double</pre>

<p>If it were the case that the <code>size_t </code>in the middle were converted to <code>int</code>, then all would be well. But it isnâ€™t. If I look at the typeid of  <code>data[0].size()/2</code> (and even demangle it, then it is <code>unsigned int</code> on a 32bit build and <code>unsigned long</code> on a 64bit build. The same is true for <code>xpos - data[0].size()/2</code>. What this leads to is that it isnâ€™t the <code>size_t</code> that is converted to <code>int</code>, it is the <code>int </code>that is converted to <code>size_t</code>. <code>xpos</code> ranges from 0 to 59, and <code>data[0].size()/2</code> is 30. So when <code>xpos</code> is less than 30, the result is negative. Or it would be if the expression type were not <code>size_t</code>, which has no negative values. Instead it wraps around to a very high positive number.</p>

<p>The fix for this is quite simple. Instead of using literal <code>2</code> in the expression, use <code>2.0</code>, thus</p>

<pre class="programlisting">
  return origin.real() + (xpos -
    data[0].size()/2.0) / scale;</pre>
	
<p>the types this time are</p>

<pre class="programlisting">
  double + (int - size_t/double) / double</pre>

<p>This time, in the subexpression <code>size_t/double</code>, the <code>size_t</code> gets converted to <code>double</code>, which again happens for <code>(int - double)</code>. Since <code>double</code> has no problem representing negative numbers, this works as intended. The same change needs to be made in <code>ycoord</code>.</p>

<p>This is one of my pet peeves, people using literals of the wrong type in expressions. Iâ€™ve even seen stuff like <code>(double)2)</code> rather than the more obvious <code>2.0</code>.</p>

<p>Lastly, how could these have been avoided? Well, both mistakes were well formed C++, so the compiler was of no help. The huge numbers produced by <code>xcoord</code> could have been detected fairly easily with a bit of analysis of what the expected upper and lower bounds are, and a suitable <code>assert</code>. </p>

<p>Finally, the initialization expression for <code>c</code>. As <code>0.0</code> is perfectly valid for <code>c.imag()</code>, an <code>assert</code> wonâ€™t help. </p>

<p>A unit test could be used, but that would require considerable changes to break up <code>Mandelbrot::operator()</code>, which I think would be excessive, so that leaves good old fashioned functional testing and debugging.</p>

<h3>Jim Segrave</h3>

<p>Problems with this code:</p>

<p>The member functions <code>xcoord</code> and <code>ycoord</code> donâ€™t work as intended. The sub-expressions involved will be evaluated as integers and conversion to <code>double</code> comes too late, their fractional part will have been truncated. A simple fix is to change the divisor from <code>2</code> (an integral value) to <code>2.0L</code>, a <code>double</code> value. Then the parenthesised sub-expressions will evaluate as doubles and the results are what is expected.</p>

<p>The second major problem is in the statement:</p>

<pre class="programlisting">
  std::complex&lt;double&gt; c = 
    (xcoord(x), ycoord(y)), z = c;</pre>
	
<p>This does not call the constructor for a complex <code>double</code> with a <code>real</code> and an imaginary part. Instead, the parenthesised expression is treated as a pair of expressions separated by a comma â€“ the <code>ycoord()</code> result is discarded and the complex <code>double</code> is constructed using the single argument constructor which sets the imaginary component to <code>0</code> and only initialises the real component. Changing the declaration to use a braced initialiser fixes this problem.</p>

<p>The compiler, with sufficient warnings enabled, should complain about mixing signed and unsigned values in the comparisons in the two for statements which iterate over <code>x</code> and <code>y</code>. Changing the types for <code>x</code> and <code>y</code> to <code>size_t</code>s (and similarly changing the <code>xcoord()</code> and <code>ycoord()</code> functions to expect <code>size_t</code> arguments, clears this warning.</p>

<p>Finally, the compiler may complain about the initialisation of the variable <code>data</code>. This variable is an C++ array of C-arrays of rows, where a row is a C++ array of a C <code>array</code> of bools. To initialise this, data needs to initialise the C++ array of rows, so it needs a pair of curly braces. Within that pair, you need an initialiser for a C array of rows, hence another pair of curly braces within the first one, which should contain an initialiser for a row. That calls for a third set of curly braces, which should contain an initialiser for a C array of bools. That needs a fourth set of curly braces around a false value:</p>

<pre class="programlisting">
  matrix data{ { { { 0 }} }}
              1 2 3 4</pre>

<p style="margin-left:1em">1 is the initialiser list for data</p>
<p style="margin-left:1em">2 is the initialiser list for a C array of rows</p>
<p style="margin-left:1em">3 is the initialiser list for a row</p>
<p style="margin-left:1em">4 is the initialiser list for a C array of bools</p>

<p>Itâ€™s ugly, but thatâ€™s what g++ 4.8 and clang 3.5.1 want to see.</p>

<p>With those corrections, the program compiles without warnings or errors and produces the expected output. However, it can be improved:</p>

<p>A Mandelbrot set is symmetric around the X axis, so it seems the program should produce a symmetric pattern. It also seems reasonable to expect that the origin point (-0.5, 0) should be plotted. But with an even number of output lines (40 in this case), there are 20 lines printed above the X axis and 19 below the X axis. For the same reasons, there are 30 points plotted to the left of the Y axis and 29 to the right. I changed the number of rows and columns to 41 and 61, which makes the output symmetrical around the origin point, but the origin point itself is no longer plotted. I altered <code>xcoord</code> and <code>ycoord</code> so that they will plot an equal number of rows above and below the origin and an equal number of columns left and right of the origin, while still plotting the X row and Y column passing through the origin.</p>

<p>A final change is one of my pet obsessions â€“ there are <code>if</code> statements in this code which control a single statement and omit any braces to make the controlled statement a compound one. Omitting the braces is a recipe for introducing bugs into code in the future. It is my firm belief that no <code>if</code>, <code>for</code>, <code>do</code> or <code>while</code> statement should ever omit the braces to make any controlled code (even an empty statement) be a compound statement. </p>

<p>Then anyone adding statements later will be forced to notice and respect the statement blocks.</p>

<p>The updated code is:</p>

<pre class="programlisting">
  #include &lt;array&gt;
  #include &lt;complex&gt;
  #include &lt;iostream&gt;
  using row = std::array&lt;bool, 61&gt;;
  using matrix = std::array&lt;row, 41&gt;;
  std::ostream&amp; operator&lt;&lt;(std::ostream &amp;os,
    row const &amp;rhs)
  {
    for (auto const &amp;v : rhs) {
      os &lt;&lt; &quot;* &quot;[v];
    }
    return os;
  }
  std::ostream&amp; operator&lt;&lt;(std::ostream &amp;os, 
    matrix const &amp;rhs)
  {
    for (auto const &amp;v : rhs) {
      os &lt;&lt; v &lt;&lt; '\n';
    }
    return os;
  }
  class Mandelbrot
  {
    matrix data = {{ {{ 0 }} }};
    std::complex&lt;double&gt; origin = (-0.5);
    double scale = 20.0;
  public:
    matrix const &amp; operator()()
    {
      for (size_t y(0); y != data.size(); ++y)
      {
        for (size_t x(0); x != data[y].size(); 
             ++x)
        {
          // use braced initialiser list for c
          std::complex&lt;double&gt;
            c{xcoord(x), ycoord(y)}, z = c;
          int k = 0;
          for (; k &lt; 200; ++k)
          {
            z = z*z + c;
            if (abs(z) &gt;= 2)
            {
              data[y][x] = true;
              break;
            }
          }
        }
      }
      return data;
    }
  private:
    double xcoord(size_t xpos)
    {
      return origin.real() +
        (xpos - (data[0].size() - 1)/2.0L)
          / scale;
    }
    double ycoord(size_t ypos)
    {
      return origin.imag() + 
        ((data.size() - 1)/2.0L - ypos)
          / scale;
    }
  };
  int main()
  {
    Mandelbrot set;
    std::cout &lt;&lt; set() &lt;&lt; std::endl;
  }</pre>

<h3>James Holland</h3>

<p>The first thing to do is to clear the decks by getting rid of any compiler warnings. My compiler issues warnings about the comparisons between signed and unsigned integer expressions that occur in the two outer <code>for</code> statements of <code>operator()();</code> The problem is that <code>data[y].size()</code> and <code>data.size()</code> return unsigned types while the variables used in the comparison, <code>x</code> and <code>y</code>, are signed types. It would be convenient to ask the <code>std::array</code> what type it uses for representing sizes and to use that. This is achieved by referring to the <code>std::array</code>â€™s public definition of <code>size_type</code> as shown below.</p>

<pre class="programlisting">
  for (row::size_type y(0);
     y != data.size(); ++y)
  for (matrix::size_type x(0);
     x != data[y].size(); ++x) </pre>

<p>Unfortunately, the software still behaves in the same unexpected way. After quite a bit of effort it was discovered that <code>xcoord()</code> and <code>ycoord()</code> are not returning correct values. Investigations revealed that using both signed and unsigned types in the return expression are to blame. As noted above, <code>data[0].size()</code> and <code>data.size()</code> return unsigned types while <code>xpos</code> and <code>ypos</code> are of type <code>unsigned int</code>. C++ has set of rules it uses to determine how to handle situations like this. It turns out that, in this case, signed values are converted to unsigned types. The result of the expression is also unsigned. This has the consequence that what was thought to be small negative numbers are manipulated as if they were large positive numbers. This accounts for <code>xcoord()</code> and <code>ycoord()</code> returning unexpected values.</p>

<p>In our situation, there are two ways in which the problem of signed values can be resolved. Probably the most direct way is to cast the unsigned value to signed values as shown below. </p>

<pre class="programlisting">
  double xcoord(int xpos)
  {
    return origin.real() +
      (xpos - static_cast&lt;signed int&gt; 
        (data[0].size())/2) / scale;
  }
  double ycoord(int ypos)
  {
    return origin.imag() +
      (static_cast&lt;signed int&gt;(data.size())/2 - 
       ypos) / scale;
  }</pre>
  
<p>This works well where the sizes of the dimensions of data are even numbers. Dividing such numbers by 2 (as is done in <code>xcoord()</code> and <code>ycoord()</code>) results in no loss of information. Had the sizes been represented by odd numbers, dividing by 2 would lose the fractional part of the result. In such cases it would, perhaps, be simpler to make the divisor a <code>double</code> instead of a <code>signed int</code>. This can be achieved by simply replacing the <code>2</code> in <code>xcoord()</code> and <code>ycoord()</code> with <code>2.0</code>. Dividing an unsigned type by a <code>double</code> will result in a <code>double</code> which is inherently signed and will preserve any remainder. For the problem at hand, I have chosen the casting method as it makes clear the intentions of the programmer and, as the <code>size()</code> value is even, dividing by a <code>double</code> is not necessary.</p>

<p>Having corrected <code>xcoord()</code> and <code>ycoord()</code> it is disappointing to discover that the program still does not produce the expected result. Further investigation is required. It turns out that the initialisation of <code>c</code> is at fault. C++ allows variables to be correctly initialised in a variety of ways but there are a few cases where what seems obvious are inappropriate. This is one of them. In this case, the values within the parenthesise of the initialisation of <code>c</code> are being interpreted as arguments of a comma operator. The result is that the first value (<code>xcoord(x)</code>) is ignored and the second value (<code>ycoord(y)</code>) is copied to the real part of <code>c</code>. The imaginary part is automatically set to zero. This is not what is required. Correct initialisation of <code>c</code> is achieved by any of the following statements.</p>
 
<pre class="programlisting">
  std::complex&lt;double&gt; c{xcoord(x), ycoord(y)};
  std::complex&lt;double&gt; c 
    = {xcoord(x), ycoord(y)};
  std::complex&lt;double&gt; c(xcoord(x), ycoord(y));</pre>

<p>The use of parentheses (<code>(</code> and <code>)</code>) and braces (<code>{</code> and <code>}</code>) both have their advantages and disadvantages so it is largely a matter of choice as to which is used. It is probably best to be consistent throughout the program, however.</p>

<p>Having resolved the initialisation problem, the program should work as expected with the display of the Mandelbrot set. There are, however, a couple of amendments that could be made to improve the appearance of the source code. As mentioned above, a consistent initialisation approach would be beneficial. The initialisation of data, origin and scale uses three different syntaxes. The initialisation of <code>x</code> and <code>y</code> uses yet another. I suggest, for no particularly strong reason, that brace initialisation is used throughout. Another slightly curious feature is the declaration of <code>k</code> just before the for loop. <code>k</code> would be better declared as part of the <code>for</code> loop as it is not required outside the scope of the loop.</p>

<p>For completeness, I provide the corrected program.</p>

<pre class="programlisting">
  #include &lt;array&gt;
  #include &lt;complex&gt;
  #include &lt;iostream&gt;
  using row = std::array&lt;bool, 60&gt;;
  using matrix = std::array&lt;row, 40&gt;;
  std::ostream &amp; operator&lt;&lt;(std::ostream &amp;os,
    row const &amp;rhs)
  {
    for (auto const &amp;v : rhs)
      os &lt;&lt; &quot;* &quot;[v];
    return os;
  }
  std::ostream &amp; operator&lt;&lt;(std::ostream &amp;os, 
    matrix const &amp;rhs)
  {
    for (auto const &amp;v : rhs)
      os &lt;&lt; v &lt;&lt; '\n';
    return os;
  }
  class Mandelbrot
  {
    matrix data{};
    std::complex&lt;double&gt; origin{-0.5};
    double scale{20.0};
  public:
    matrix const &amp; operator()()
    {
      for (row::size_type y{0};
           y != data.size(); ++y)
      {
        for (matrix::size_type x{0};
             x != data[y].size(); ++x)
        {
          std::complex&lt;double&gt; 
            c{xcoord(x), ycoord(y)}, z = c;
          for (int k{0}; k &lt; 200; ++k)
          {
            z = z * z + c;
            if (abs(z) &gt;= 2)
            {
              data[y][x] = true;
              break;
            }
          }
        }
      }
      return data;
    }
  private:
    double xcoord(int xpos)
    {
      return origin.real() + (xpos -
        static_cast&lt;signed int&gt;(data[0].size()) 
          /2) / scale;
    }
    double ycoord(int ypos)
    {
      return origin.imag() + 
     (static_cast&lt;signed int&gt;(data.size())/2 -
        ypos) / scale;
    }
  };
  int main()
  {
    Mandelbrot set;
    std::cout &lt;&lt; set() &lt;&lt; std::endl;
  }</pre>

<h2>Commentary</h2>

<p>This problem was, it seems, a little frustrating to analyse. This is partly because there were two unrelated bugs and finding and fixing just one of them was not enough to produce sensible output.</p>

<p>Fortunately many of our debugging tasks involve a single root cause of the problem, but it is worth remembering that this is not always the case, even in short code fragments like this one.</p>

<p>I think between them the critiques covered most of the issues. One issue no-one covered is that the <code>operator&lt;&lt;</code> defined for row and matrix are in the default namespace and use types from the <code>std</code> namespace so there is potential for a violation of the One Definition Rule if another source file in the final executable were to define the same operator on one of the types.</p>

<p>The odd placement of <code>k</code> outside the <code>for</code> loop was historical â€“ the original program used the final value of <code>k</code> to produce a more flexible output than just a simple boolean value.</p>

<h2>The winner of CC93</h2>

<p>There were good points made by all entrants. I also note that all three entries referred to removing compiler warnings: I take this as a good sign that warnings are getting better and/or programmers are learning to use the inbuilt static detection provided by the compiler. Paul did not actually remove the warnings though â€“ it might have been useful for a critique to have explained why they werenâ€™t directly relevant in this case.</p>

<p>There are many problems that can be caused by mixing types, particularly signed and unsigned integers. In this case dividing by 2.0 rather than 2 fixed the problem, but primarily because double is signed rather than because of truncation as Jim suggested â€“ but doing this does avoid problems if the program changes in the future.</p>

<p>There are now many different ways to initialise variables in C++ and Jamesâ€™ preference for use of a consistent initialisation style in a single source file is a good idea and one likely to reduce errors. (Scott Meyersâ€™ recommendation in Item 7 of <em>Effective Modern C++</em> is to use brace initialisation where possible.)</p>

<p>I liked Paulâ€™s final reflective question â€œLastly, how could these have been avoidedâ€ â€“ even though in this case there are few quick answers â€“ and overall his critique wins the prize by a short head.</p>


<h2>Code Critique 94</h2>

<p>(Submissions to scc@accu.org by August 1st)</p>

<p class="blockquote">I had some code that used an anonymous structure within an anonymous union to easily refer to the high and low 32-bit parts of a 64-bit pointer. However, I get a warning that this is non-portable (I'm not quite sure why - MSVC and g++ both accept it) but after googling around for a solution I found one that uses #define. It all compiles without warnings now so I think it's fixed.</p>

<p>Can you give some advice to help this programmer? The code is in Listing 2.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
--- address.h ---
#pragma once
typedef struct {
  union {
    struct {
      int32_t offsetLo;
      int32_t offsetHi;
    } s;
    void *pointer;
  };
} address;
// simulate anonymous structs with #define
#define offsetLo s.offsetLo
#define offsetHi s.offsetHi

--- test program ---
#include &lt;cstdint&gt;
#include &lt;iostream&gt;
#include &quot;address.h&quot;
int main()
{
  int var = 12;
  address a;
  a.pointer = &amp;var;
  std::cout &lt;&lt; &quot;Address = &quot; &lt;&lt; std::hex
    &lt;&lt; a.offsetHi &lt;&lt; &quot;/&quot; &lt;&lt; a.offsetLo
    &lt;&lt; std::endl;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>You can also get the current problem from the accu-general mail list (next entry is posted around the last issueâ€™s deadline) or from the ACCU website (<a href="http://www.accu.org/journals/">http://www.accu.org/journals/</a>). This particularly helps overseas members who typically get the magazine much later than members in the UK and Europe.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
