🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.c.moderated
Article #2369

Re: Macros and Braces

#2369
From: Stig Hemmer
Date: Sun, 24 Mar 1996 17:41
75 lines
2958 bytes
In article <4j06iu$7qm@solutions.solon.com> 100576.1776@compuserve.com (Antony Pace (UK/CH)) writes:
[How can I write a macro that works like a function in all contexts?]

There are many ways, here are some variants of your methods:
> #define CLEAR_ERROR(e) \
>   clear_error(e)
> 
> void clear_error(t_error error) {
>   (error).a = 0;            
>   (error).b = 0;           
>   (error).c = 0;           
>   TRACE("clear error");
> }

Try:
#define CLEAR_ERROR(e) \
  clear_error(e,__FILE__,__LINE__)

You'll need another macro TRACE2 which accepts file and line arguments
but this is just a minor rewrite of TRACE. And you can do

#define TRACE(s) TRACE2(s,__FILE__,__LINE__)

If this is something you do often, you probably don't want the
function call overhead though...

>#define CLEAR_ERROR(e)  \
>  (e).a = 0, (e).b = 0 ,  (e).c = 0 , TRACE("clear error")
>
>which expands to 
>
>  (e).a = 0, (e).b = 0 ,  (e).c = 0 ,  if (trace_on)
>    fprintf(trace_file, __FILE__ __LINE__ "%s", "clear error")
>  ;
>
>The semicolon is now a statement separator and not a null statement, but
>the TRACE expands to an if statement which does not work with the comma
>expression.

Rewrite TRACE as an expression too and it will work:
#define TRACE (trace_on && fprintf(...))


> #define CLEAR_ERROR(e) \
>   if (!((e).a = (e).b = (e).c = 0)) TRACE("clear error")

> It uses an unnecessary comparison which I don't like but at least it
> works!

Never mind the comparison, the compiler will probably optimize it away
anyway. Another similar way of doing this:

#define CLEAR_ERROR(e)\
   do {\
      ...\
   } while(0)

Again a good compiler should kill the comparison. In this version
"..." can be anything, not just expressions.

>As I said at the top, I am sure that I am not the first with this
>problem and would love to hear of THE clean solution.  Thanks very much.

As you can see, there are many ways of solving this problem. The last
one is IMHO closest to being THE solution since it can be used
regardless what you want to do in the macro. In fact, I have a feeling
that this is the 'traditional' way of solving this problem, though I
can't really remember where I learnt it first.

Happy hacking!

Stig Hemmer   aka   stig@pvv.unit.no
pvv   - ProgramVareVerkstedet ("The Software Workshop", a student society)
.unit - UNiversitetet I Trondheim
.no   - NOrway, a minor kingdom in northern Europe.           Yes in 2016!
Technical Details
Message-ID: <4j41fn$nha@solutions.solon.com>
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
References: <4j06iu$7qm@solutions.solon.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail
From: stig@pvv.unit.no (Stig Hemmer)
Newsgroups: comp.lang.c.moderated
Subject: Re: Macros and Braces
Date: 24 Mar 1996 11:41:11 -0600
Organization: Norwegian University of Science and Technology
Sender: clc@solutions.solon.com
Approved: clc@solutions.solon.com
Message-ID: <4j41fn$nha@solutions.solon.com>
References: <4j06iu$7qm@solutions.solon.com>
NNTP-Posting-Host: solutions.solon.com
X-Newsreader: Gnus v5.1