<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Stupid C++ Tricks: do/while(0) and C4127</title>
	<atom:link href="http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/feed/" rel="self" type="application/rss+xml" />
	<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/</link>
	<description>programming is hard.</description>
	<lastBuildDate>Sun, 05 Feb 2012 15:43:05 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: charles</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-83</link>
		<dc:creator>charles</dc:creator>
		<pubDate>Thu, 29 Jul 2010 18:46:28 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-83</guid>
		<description>Regarding &quot;__pragma&quot; and &quot;this won&#039;t even compile&quot;, I&#039;m not sure what you&#039;re talking about.

http://msdn.microsoft.com/en-us/library/d9x1s805.aspx

Details how it works, and it does work, successfully, on both VS2005 and VS2008.  I didn&#039;t care so much about other compilers than MSVC and gcc for this experiment, but since gcc doesn&#039;t have an equivalent warning, it didn&#039;t matter for me.

I&#039;m not sure why &quot;while (true, false)&quot; wouldn&#039;t trigger it, but I wouldn&#039;t be surprised to see it start issuing a warning as compilers get better...</description>
		<content:encoded><![CDATA[<p>Regarding &#8220;__pragma&#8221; and &#8220;this won&#8217;t even compile&#8221;, I&#8217;m not sure what you&#8217;re talking about.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/d9x1s805.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/d9x1s805.aspx</a></p>
<p>Details how it works, and it does work, successfully, on both VS2005 and VS2008.  I didn&#8217;t care so much about other compilers than MSVC and gcc for this experiment, but since gcc doesn&#8217;t have an equivalent warning, it didn&#8217;t matter for me.</p>
<p>I&#8217;m not sure why &#8220;while (true, false)&#8221; wouldn&#8217;t trigger it, but I wouldn&#8217;t be surprised to see it start issuing a warning as compilers get better&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ernst Rattenhuber</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-80</link>
		<dc:creator>Ernst Rattenhuber</dc:creator>
		<pubDate>Mon, 21 Jun 2010 16:50:59 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-80</guid>
		<description>I guess someone will point out to me why the following idea is no good:

instead of...
do { } while (FALSE)

...I defined a global constant and modified the macro to...
do { } while (myAlwaysFalseConstant)

This doesn&#039;t produce a warning (at least not in the environments I&#039;ve tested: Visual Studio 2008 and TI&#039;s Code Composer 3.3 for the 320C6400 DSP family) and doesn&#039;t rely on undocumented compiler behavior. It does produce slightly more code than do { } while (FALSE), but very marginally so.

For me, wishing to support both a Visual Studio environment for off-line testing and a DSP environment for target code, the do { } while (__LINE__ == -1) alternative is not an option.

Of course, some people dislike globals as a matter of principle. When you tell me the idea is no good, I shall expect a better reason than that ;-)</description>
		<content:encoded><![CDATA[<p>I guess someone will point out to me why the following idea is no good:</p>
<p>instead of&#8230;<br />
do { } while (FALSE)</p>
<p>&#8230;I defined a global constant and modified the macro to&#8230;<br />
do { } while (myAlwaysFalseConstant)</p>
<p>This doesn&#8217;t produce a warning (at least not in the environments I&#8217;ve tested: Visual Studio 2008 and TI&#8217;s Code Composer 3.3 for the 320C6400 DSP family) and doesn&#8217;t rely on undocumented compiler behavior. It does produce slightly more code than do { } while (FALSE), but very marginally so.</p>
<p>For me, wishing to support both a Visual Studio environment for off-line testing and a DSP environment for target code, the do { } while (__LINE__ == -1) alternative is not an option.</p>
<p>Of course, some people dislike globals as a matter of principle. When you tell me the idea is no good, I shall expect a better reason than that <img src='http://cnicholson.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jumpster</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-78</link>
		<dc:creator>Jumpster</dc:creator>
		<pubDate>Sun, 23 May 2010 15:21:47 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-78</guid>
		<description>I have the following macro definitions that tells the compiler to shut-up about unused variables/parameter; which have recently been changed from the old stand-by:

[code]
  #define UNUSED(var) (var)
[/code]

to:

[code]
  //********************************************************** 
  // Nifty little helper macros that are used *everywhere*
  //********************************************************** 
  #define UNUSED(var)          MACRO_BEGIN                \
                                 (void)sizeof(var);       \
                               MACRO_END
  #define UNUSED_VARIABLE(var)  UNUSED(var)
  #define UNUSED_PARAMETER(prm) UNUSED(prm)
[/code]


Now, I have tried virtually every alternative presented within this article and related comments except for the try/catch above to accomplish 3 things:

1) Avoid the C4127 warning,
2) Remove/reduce the required assembly code to shut-up the compiler, and;
3) if possible, remove compiler dependancy from the code (ie: Microsoft VC++)

Here&#039;s what I found out...

[code]
  #define MACRO_END   } while(__LINE__ == -1)
[/code]

still gives me the C4127 warning - I am running VC++ 2008 w/sp1 - So I will continue to test other alternatives...

[code]
  inline bool False(void) {return false; }
  #define MACRO_BEGIN   do {
  #define MACRO_END     } while(False())
[/code]

My first thoughts were that this would &quot;optimize out&quot; the *call* to False() and replace it with a simple MOV EAX, 0 - but this didn&#039;t happen. Instead, I got the following generated assembly code...

[code]
$LN3@Update:

; 494  :     UNUSED_PARAMETER(elapsed_time);

  01297	e8 00 00 00 00	 call	 ?False@TOOLBOX@@YA_NXZ	; TOOLBOX::False
  0129c	0f b6 c0	 movzx	 eax, al
  0129f	85 c0		 test	 eax, eax
  012a1	75 f4		 jne	 SHORT $LN3@Update

[/code]

Notice the call to False() is still there. Of course, it&#039;s immediately followed by the mov instruction I was expecting (a variant anyway). I noticed that the move was dealing with al (1-byte) - duh... type bool is 1-byte so this makes sense... I then replaced the False() function with the following definition...

[code]
inline int False(void) { return 0; }
[/code]

and this time the generated code looks like:

[code]
$LN3@Update:

; 494  :     UNUSED_PARAMETER(elapsed_time);

  01297	e8 00 00 00 00	 call	 ?False@TOOLBOX@@YAHXZ	; TOOLBOX::False
  0129c	85 c0		 test	 eax, eax
  0129e	75 f7		 jne	 SHORT $LN3@Update
[/code]

Better, but notice the call to False() is still there... Maybe that has something to do with my compiler settings, but I don&#039;t want to have to &quot;tweak&quot; the compiler for this one macro / function...

So, I moved on to the next alternative...

[code]
  #define MACRO_END        \
    __pragma(warning(push)) \   
    __pragma(warning(disable:4127)) \   
    } while(0) \   
    __pragma(warning(pop))  
[/code]

This doesn&#039;t even compile. I get &quot;error C2017: illegal escape sequence&quot; and related messages... In addition, __pragma() is Microsoft specific. I really don&#039;t like this alternative anyway so on to the next...

[code]
  #define MACRO_END     } while(true,false)
[/code]

Now this is promising... This version generates the following assembly code and as far as I know, is not compiler dependant nor does it generate a C4127 warning...

[code]
$LN3@Update:

; 494  :     UNUSED_PARAMETER(elapsed_time);

  01297	33 c0		 xor	 eax, eax
  01299	75 fc		 jne	 SHORT $LN3@Update
[/code]


So, as a test, I set the MACRO_END definition back to the original:

[code]
  #define MACRO_END  } while(0)
[/code]

and accepting the C4127 warning, I wanted to see the generated code and with this I get the following assembly output:

[code]
$LN3@Update:

; 494  :     UNUSED_PARAMETER(elapsed_time);

  01297	33 c0		 xor	 eax, eax
  01299	75 fc		 jne	 SHORT $LN3@Update
[/code]

Which is identical to the version immediately above...

Therefore, it seems to me that the method of defining MACRO_END as:

[code]
  #define MACRO_END     } while(true,false)
[/code]

satisfies my requirements. So in conclusion, I will be sticking to the while (true,false) variety as proposed by Phill Djonov above. Thanks Phill!

NOTE: All of the above generated code was for x86 in RELEASE build. I have no idea of the generated Itanium or what-not processor&#039;s code. Ideally, I&#039;d like to remove the xor and jne instructions too, however, they appear to be a by-product of the do..while() loop. As arguments for their inclusion seems to be reasonable, I guess I will continue with this approach. Anyone know of a way to eliminate those?

Jumpster</description>
		<content:encoded><![CDATA[<p>I have the following macro definitions that tells the compiler to shut-up about unused variables/parameter; which have recently been changed from the old stand-by:</p>
<p>[code]<br />
  #define UNUSED(var) (var)<br />
[/code]</p>
<p>to:</p>
<p>[code]<br />
  //**********************************************************<br />
  // Nifty little helper macros that are used *everywhere*<br />
  //**********************************************************<br />
  #define UNUSED(var)          MACRO_BEGIN                \<br />
                                 (void)sizeof(var);       \<br />
                               MACRO_END<br />
  #define UNUSED_VARIABLE(var)  UNUSED(var)<br />
  #define UNUSED_PARAMETER(prm) UNUSED(prm)<br />
[/code]</p>
<p>Now, I have tried virtually every alternative presented within this article and related comments except for the try/catch above to accomplish 3 things:</p>
<p>1) Avoid the C4127 warning,<br />
2) Remove/reduce the required assembly code to shut-up the compiler, and;<br />
3) if possible, remove compiler dependancy from the code (ie: Microsoft VC++)</p>
<p>Here&#8217;s what I found out&#8230;</p>
<p>[code]<br />
  #define MACRO_END   } while(__LINE__ == -1)<br />
[/code]</p>
<p>still gives me the C4127 warning &#8211; I am running VC++ 2008 w/sp1 &#8211; So I will continue to test other alternatives&#8230;</p>
<p>[code]<br />
  inline bool False(void) {return false; }<br />
  #define MACRO_BEGIN   do {<br />
  #define MACRO_END     } while(False())<br />
[/code]</p>
<p>My first thoughts were that this would &#8220;optimize out&#8221; the *call* to False() and replace it with a simple MOV EAX, 0 &#8211; but this didn&#8217;t happen. Instead, I got the following generated assembly code&#8230;</p>
<p>[code]<br />
$LN3@Update:</p>
<p>; 494  :     UNUSED_PARAMETER(elapsed_time);</p>
<p>  01297	e8 00 00 00 00	 call	 ?False@TOOLBOX@@YA_NXZ	; TOOLBOX::False<br />
  0129c	0f b6 c0	 movzx	 eax, al<br />
  0129f	85 c0		 test	 eax, eax<br />
  012a1	75 f4		 jne	 SHORT $LN3@Update</p>
<p>[/code]</p>
<p>Notice the call to False() is still there. Of course, it&#8217;s immediately followed by the mov instruction I was expecting (a variant anyway). I noticed that the move was dealing with al (1-byte) &#8211; duh&#8230; type bool is 1-byte so this makes sense&#8230; I then replaced the False() function with the following definition&#8230;</p>
<p>[code]<br />
inline int False(void) { return 0; }<br />
[/code]</p>
<p>and this time the generated code looks like:</p>
<p>[code]<br />
$LN3@Update:</p>
<p>; 494  :     UNUSED_PARAMETER(elapsed_time);</p>
<p>  01297	e8 00 00 00 00	 call	 ?False@TOOLBOX@@YAHXZ	; TOOLBOX::False<br />
  0129c	85 c0		 test	 eax, eax<br />
  0129e	75 f7		 jne	 SHORT $LN3@Update<br />
[/code]</p>
<p>Better, but notice the call to False() is still there&#8230; Maybe that has something to do with my compiler settings, but I don&#8217;t want to have to &#8220;tweak&#8221; the compiler for this one macro / function&#8230;</p>
<p>So, I moved on to the next alternative&#8230;</p>
<p>[code]<br />
  #define MACRO_END        \<br />
    __pragma(warning(push)) \<br />
    __pragma(warning(disable:4127)) \<br />
    } while(0) \<br />
    __pragma(warning(pop))<br />
[/code]</p>
<p>This doesn&#8217;t even compile. I get &#8220;error C2017: illegal escape sequence&#8221; and related messages&#8230; In addition, __pragma() is Microsoft specific. I really don&#8217;t like this alternative anyway so on to the next&#8230;</p>
<p>[code]<br />
  #define MACRO_END     } while(true,false)<br />
[/code]</p>
<p>Now this is promising&#8230; This version generates the following assembly code and as far as I know, is not compiler dependant nor does it generate a C4127 warning&#8230;</p>
<p>[code]<br />
$LN3@Update:</p>
<p>; 494  :     UNUSED_PARAMETER(elapsed_time);</p>
<p>  01297	33 c0		 xor	 eax, eax<br />
  01299	75 fc		 jne	 SHORT $LN3@Update<br />
[/code]</p>
<p>So, as a test, I set the MACRO_END definition back to the original:</p>
<p>[code]<br />
  #define MACRO_END  } while(0)<br />
[/code]</p>
<p>and accepting the C4127 warning, I wanted to see the generated code and with this I get the following assembly output:</p>
<p>[code]<br />
$LN3@Update:</p>
<p>; 494  :     UNUSED_PARAMETER(elapsed_time);</p>
<p>  01297	33 c0		 xor	 eax, eax<br />
  01299	75 fc		 jne	 SHORT $LN3@Update<br />
[/code]</p>
<p>Which is identical to the version immediately above&#8230;</p>
<p>Therefore, it seems to me that the method of defining MACRO_END as:</p>
<p>[code]<br />
  #define MACRO_END     } while(true,false)<br />
[/code]</p>
<p>satisfies my requirements. So in conclusion, I will be sticking to the while (true,false) variety as proposed by Phill Djonov above. Thanks Phill!</p>
<p>NOTE: All of the above generated code was for x86 in RELEASE build. I have no idea of the generated Itanium or what-not processor&#8217;s code. Ideally, I&#8217;d like to remove the xor and jne instructions too, however, they appear to be a by-product of the do..while() loop. As arguments for their inclusion seems to be reasonable, I guess I will continue with this approach. Anyone know of a way to eliminate those?</p>
<p>Jumpster</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Christophe Grosjean</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-76</link>
		<dc:creator>Christophe Grosjean</dc:creator>
		<pubDate>Thu, 14 Jan 2010 16:33:17 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-76</guid>
		<description>Well, you are right. It does not eat semicolon, Hence a try catch as I proposed is in no way better than a simple brackets pair. Too bad. Back to do {} while(0) trick... or back to inline functions if you use C++. 

I disagree with the comment about destructors. You can use try catch in destructors, the only thing that is calling for problems is throwing exceptions outside destructors. Even more, you **should** catch every exceptions possibly thrown by functions called in a destructor or it will go outside and **then** you will have problems...</description>
		<content:encoded><![CDATA[<p>Well, you are right. It does not eat semicolon, Hence a try catch as I proposed is in no way better than a simple brackets pair. Too bad. Back to do {} while(0) trick&#8230; or back to inline functions if you use C++. </p>
<p>I disagree with the comment about destructors. You can use try catch in destructors, the only thing that is calling for problems is throwing exceptions outside destructors. Even more, you **should** catch every exceptions possibly thrown by functions called in a destructor or it will go outside and **then** you will have problems&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: charles</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-71</link>
		<dc:creator>charles</dc:creator>
		<pubDate>Mon, 28 Dec 2009 17:56:12 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-71</guid>
		<description>Because your simpler example doesn&#039;t work.

#define MULTI() { std::printf(&quot;Hello&quot;); std::printf(&quot; world!\n&quot;); }

fails when you do this:

if (a)
  MULTI();
else
  MULTI();

The semicolons create syntax errors.

[WORDPRESS HASHCASH] The poster sent us &#039;0 which is not a hashcash value.</description>
		<content:encoded><![CDATA[<p>Because your simpler example doesn&#8217;t work.</p>
<p>#define MULTI() { std::printf(&#8220;Hello&#8221;); std::printf(&#8221; world!\n&#8221;); }</p>
<p>fails when you do this:</p>
<p>if (a)<br />
  MULTI();<br />
else<br />
  MULTI();</p>
<p>The semicolons create syntax errors.</p>
<p>[WORDPRESS HASHCASH] The poster sent us &#8217;0 which is not a hashcash value.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Somebody_someone</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-70</link>
		<dc:creator>Somebody_someone</dc:creator>
		<pubDate>Mon, 28 Dec 2009 11:21:37 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-70</guid>
		<description>Uff, why not simply

# #define MULTI_LINE_MACRO \  
     { \  
         std::printf(&quot;Hello &quot;); \  
         std::printf(&quot;world!\n&quot;); \  
     }

?</description>
		<content:encoded><![CDATA[<p>Uff, why not simply</p>
<p># #define MULTI_LINE_MACRO \<br />
     { \<br />
         std::printf(&#8220;Hello &#8220;); \<br />
         std::printf(&#8220;world!\n&#8221;); \<br />
     }</p>
<p>?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Seanba</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-68</link>
		<dc:creator>Seanba</dc:creator>
		<pubDate>Tue, 01 Dec 2009 16:48:21 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-68</guid>
		<description>Also, Christophe, it appears that macro wouldn&#039;t eat a trailing semicolon.</description>
		<content:encoded><![CDATA[<p>Also, Christophe, it appears that macro wouldn&#8217;t eat a trailing semicolon.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Seanba</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-67</link>
		<dc:creator>Seanba</dc:creator>
		<pubDate>Tue, 01 Dec 2009 16:40:41 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-67</guid>
		<description>Christophe, I like that solution, but unfornately you can&#039;t use that macro in a destructor without asking for serious trouble.

Not that I like the do {} while(false) trick any better, mind you. :)</description>
		<content:encoded><![CDATA[<p>Christophe, I like that solution, but unfornately you can&#8217;t use that macro in a destructor without asking for serious trouble.</p>
<p>Not that I like the do {} while(false) trick any better, mind you. <img src='http://cnicholson.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Christophe Grosjean</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-65</link>
		<dc:creator>Christophe Grosjean</dc:creator>
		<pubDate>Thu, 19 Nov 2009 14:23:36 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-65</guid>
		<description>This old C trick can be done another way with C++ without warning nor needing any pragma and sticking with the standards. I don&#039;t know if it has any performance impact.


#define MULTI_LINE_MACRO \  
    try { \  
        std::printf(&quot;Hello &quot;); \  
        std::printf(&quot;world!\n&quot;); \ 
    } catch (...) { throw; }\</description>
		<content:encoded><![CDATA[<p>This old C trick can be done another way with C++ without warning nor needing any pragma and sticking with the standards. I don&#8217;t know if it has any performance impact.</p>
<p>#define MULTI_LINE_MACRO \<br />
    try { \<br />
        std::printf(&#8220;Hello &#8220;); \<br />
        std::printf(&#8220;world!\n&#8221;); \<br />
    } catch (&#8230;) { throw; }\</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Phill Djonov</title>
		<link>http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/comment-page-1/#comment-58</link>
		<dc:creator>Phill Djonov</dc:creator>
		<pubDate>Fri, 11 Sep 2009 04:45:29 +0000</pubDate>
		<guid isPermaLink="false">http://cnicholson.net/?p=123#comment-58</guid>
		<description>Another trick that&#039;s worked for me is replacing the literal true/false with: (false, true) or (true, false) as appropriate.</description>
		<content:encoded><![CDATA[<p>Another trick that&#8217;s worked for me is replacing the literal true/false with: (false, true) or (true, false) as appropriate.</p>
]]></content:encoded>
	</item>
</channel>
</rss>

