Article View: comp.lang.c.moderated
Article #2355Macros and Braces
From: Antony Pace (UK/CH)
Date: Sat, 23 Mar 1996 06:43
Date: Sat, 23 Mar 1996 06:43
126 lines
3495 bytes
3495 bytes
Hi all,
I am having problems writing a macro (Ansi C) for which I feel there
must be standard technique. Can anyone help?
Here is my first attempt at the macro. I have defined an error type
which is a small structure with 3 variables in it. I want to use a
macro to clear all the variables so that if the number or type of
variables change, only my macro has to change.
typedef struct {
int a;
int b;
int c;
} t_error;
#define CLEAR_ERROR(e) { \
(e).a = 0; \
(e).b = 0; \
(e).c = 0; \
TRACE("clear error"); \
}
TRACE is a macro provided by another module which is approximately:
#define TRACE(s) \
if (trace_on) \
fprintf(trace_file, __FILE__ __LINE__ "%s", s);
Now, when I use my CLEAR_ERROR macro in code it works ok.
void my_fn(void) {
t_error error;
CLEAR_ERROR(error);
...
}
Note how the semicolon I put after the invocation becomes a null
statement. I expect users of my CLEAR_ERROR macro to use it, as then
the macro looks like a function call.
In this code segment, my macro does not work:
...
if (a==3)
CLEAR_ERROR(error);
else
b=5;
...
This expands to:
...
if (a==3) {
(e).a = 0;
(e).b = 0;
(e).c = 0;
TRACE("clear error");
}
; /* note the null statement */
else
b=5;
...
Of course I get an error 'else' has no 'if'.
----------------------------------------------------
Second part!
Now normally in this situation I would either combine the macro
statements to make a single statement by using the comma expression, or
I would call a function from the macro.
The comma expression
--------------------
#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.
The function call
-----------------
#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");
}
But not here what the TRACE puts in the trace file for the __FILE__ and
__LINE__ numbers. Of course it is always the same file and line.
I could just put the variable clearing in the function but then I still
have two statements in the macro and that is no better than having four.
My current implementation looks like this.
#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!
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.
Ant
Technical Details
Message-ID:
<4j06iu$7qm@solutions.solon.com>Path:
arc1-ca.pugleaf.net!solon.com!not-for-mailShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!solon.com!not-for-mail From: 100576.1776@compuserve.com (Antony Pace (UK/CH)) Newsgroups: comp.lang.c.moderated Subject: Macros and Braces Date: 23 Mar 1996 00:43:42 -0600 Organization: CompuServe Incorporated Sender: clc@solutions.solon.com Approved: clc@solutions.solon.com Message-ID: <4j06iu$7qm@solutions.solon.com> NNTP-Posting-Host: solutions.solon.com X-Newsreader: OUI 1.3.0