Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > macro

Reply
Thread Tools

macro

 
 
dspfun
Guest
Posts: n/a
 
      01-15-2012
Hi all!

Can you see anything wrong or "bad" with the following macro?

#define LOG(level, msg) \
openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
\
syslog (level, "%s", msg);\
closelog ();

I have problems using the macro with ternary operators. I believe it
should have parantheses around it all, but I cannot get it right.

Brs,
Markus
 
Reply With Quote
 
 
 
 
Dr Nick
Guest
Posts: n/a
 
      01-15-2012
dspfun <(E-Mail Removed)> writes:

> Hi all!
>
> Can you see anything wrong or "bad" with the following macro?
>
> #define LOG(level, msg) \
> openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> \
> syslog (level, "%s", msg);\
> closelog ();
>
> I have problems using the macro with ternary operators. I believe it
> should have parantheses around it all, but I cannot get it right.


Do you mean using it inside operators - like:

b==c ? LOG(10,"hello") : LOG(2,"goodbye");

If so, then you will have problems as the macro is three statements while
the ternary operator expects a single expression on each side.

If you do mean that - why are you doing it? The macro returns no value
so you'd be better with an if. If you don't mean that, what do you mean
(hint - give an example of where it's not working).

If you do want to use it with an if you need to be careful to wrap it in
{}s. You might want to use the do{ ... } while(0) trick.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
 
Reply With Quote
 
 
 
 
dspfun
Guest
Posts: n/a
 
      01-15-2012
On 15 Jan, 14:44, Dr Nick <(E-Mail Removed)> wrote:
> dspfun <(E-Mail Removed)> writes:
> > Hi all!

>
> > Can you see anything wrong or "bad" with the following macro?

>
> > #define LOG(level, msg) \
> > openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> > \
> > syslog (level, "%s", msg);\
> > closelog ();

>
> > I have problems using the macro with ternary operators. I believe it
> > should have parantheses around it all, but I cannot get it right.

>
> Do you mean using it inside operators - like:
>
> b==c ? LOG(10,"hello") : LOG(2,"goodbye");
>
> If so, then you will have problems as the macro is three statements while
> the ternary operator expects a single expression on each side.
>
> If you do mean that - why are you doing it? *The macro returns no value
> so you'd be better with an if. *If you don't mean that, what do you mean
> (hint - give an example of where it's not working).
>
> If you do want to use it with an if you need to be careful to wrap it in
> {}s. *You might want to use the do{ ... } while(0) trick.
> --
> Online waterways route planner * * * * * *|http://canalplan.eu
> Plan trips, see photos, check facilities *|http://canalplan.org.uk


Hi, thanks for your quick reply!

Here is the function/code where it is used (slightly modified, but
still is valid):

static void
foo(Boolean internal)
internal ? TRACE_IF(8, STR("Doing internal stuff\n")) : TRACE_IF(8,
STR("Not internal stuff\n"));
...snip...


TRACE_IF is defined as:

#define TRACE_IF(GROUP,MSG) LOG(LOG_INFO, MSG)


LOG is defined as:
#define LOG(level,msg) openlog (__FUNCTION__, LOG_CONS | LOG_PID |
LOG_NDELAY, LOG_USER); syslog (level, "%s", msg);closelog ();


Resulting in:

internal ? openlog (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog
(6, "%s", STR("Doing internal stuff\n"));closelog (); : openlog
(__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog (6, "%s", STR("Not
internal stuff\n"));closelog ();;


Which gives the compile error:
foo.c:737: error: expected ':' before ';' token

What would be the "proper" way to define the macro LOG above?

Brs,
Markus
 
Reply With Quote
 
Joachim Schmitz
Guest
Posts: n/a
 
      01-15-2012
dspfun wrote:
> On 15 Jan, 14:44, Dr Nick <(E-Mail Removed)> wrote:
>> dspfun <(E-Mail Removed)> writes:
>>> Hi all!

>>
>>> Can you see anything wrong or "bad" with the following macro?

>>
>>> #define LOG(level, msg) \
>>> openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
>>> \
>>> syslog (level, "%s", msg);\
>>> closelog ();

>>
>>> I have problems using the macro with ternary operators. I believe it
>>> should have parantheses around it all, but I cannot get it right.

>>
>> Do you mean using it inside operators - like:
>>
>> b==c ? LOG(10,"hello") : LOG(2,"goodbye");
>>
>> If so, then you will have problems as the macro is three statements
>> while the ternary operator expects a single expression on each side.
>>
>> If you do mean that - why are you doing it? The macro returns no
>> value so you'd be better with an if. If you don't mean that, what do
>> you mean (hint - give an example of where it's not working).
>>
>> If you do want to use it with an if you need to be careful to wrap
>> it in {}s. You might want to use the do{ ... } while(0) trick.
>> --
>> Online waterways route planner |http://canalplan.eu
>> Plan trips, see photos, check facilities |http://canalplan.org.uk

>
> Hi, thanks for your quick reply!
>
> Here is the function/code where it is used (slightly modified, but
> still is valid):
>
> static void
> foo(Boolean internal)
> internal ? TRACE_IF(8, STR("Doing internal stuff\n")) : TRACE_IF(8,
> STR("Not internal stuff\n"));
> ..snip...
>
>
> TRACE_IF is defined as:
>
> #define TRACE_IF(GROUP,MSG) LOG(LOG_INFO, MSG)
>
>
> LOG is defined as:
> #define LOG(level,msg) openlog (__FUNCTION__, LOG_CONS | LOG_PID |
> LOG_NDELAY, LOG_USER); syslog (level, "%s", msg);closelog ();
>
>
> Resulting in:
>
> internal ? openlog (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog
> (6, "%s", STR("Doing internal stuff\n"));closelog (); : openlog
> (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog (6, "%s", STR("Not
> internal stuff\n"));closelog ();;
>
>
> Which gives the compile error:
> foo.c:737: error: expected ':' before ';' token
>
> What would be the "proper" way to define the macro LOG above?


Try this:

#define LOG(level,msg) do {\
openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);\
syslog (level, "%s", msg);\
closelog (); } while (0)

Bye, Jojo
 
Reply With Quote
 
dspfun
Guest
Posts: n/a
 
      01-15-2012
On 15 Jan, 15:37, "christian.bau" <(E-Mail Removed)>
wrote:
> On Jan 15, 1:58*pm, dspfun <(E-Mail Removed)> wrote:
>
>
>
>
>
>
>
>
>
> > On 15 Jan, 14:44, Dr Nick <(E-Mail Removed)> wrote:

>
> > > dspfun <(E-Mail Removed)> writes:
> > > > Hi all!

>
> > > > Can you see anything wrong or "bad" with the following macro?

>
> > > > #define LOG(level, msg) \
> > > > openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> > > > \
> > > > syslog (level, "%s", msg);\
> > > > closelog ();

>
> > > > I have problems using the macro with ternary operators. I believe it
> > > > should have parantheses around it all, but I cannot get it right.

>
> > > Do you mean using it inside operators - like:

>
> > > b==c ? LOG(10,"hello") : LOG(2,"goodbye");

>
> > > If so, then you will have problems as the macro is three statements while
> > > the ternary operator expects a single expression on each side.

>
> > > If you do mean that - why are you doing it? *The macro returns no value
> > > so you'd be better with an if. *If you don't mean that, what do youmean
> > > (hint - give an example of where it's not working).

>
> > > If you do want to use it with an if you need to be careful to wrap itin
> > > {}s. *You might want to use the do{ ... } while(0) trick.
> > > --
> > > Online waterways route planner * * * * * *|http://canalplan.eu
> > > Plan trips, see photos, check facilities *|http://canalplan.org.uk

>
> > Hi, thanks for your quick reply!

>
> > Here is the function/code where it is used (slightly modified, but
> > still is valid):

>
> > static void
> > foo(Boolean internal)
> > internal ? TRACE_IF(8, STR("Doing internal stuff\n")) : TRACE_IF(8,
> > STR("Not internal stuff\n"));
> > ..snip...

>
> > TRACE_IF is defined as:

>
> > #define TRACE_IF(GROUP,MSG) LOG(LOG_INFO, MSG)

>
> > LOG is defined as:
> > #define LOG(level,msg) openlog (__FUNCTION__, LOG_CONS | LOG_PID |
> > LOG_NDELAY, LOG_USER); syslog (level, "%s", msg);closelog ();

>
> > Resulting in:

>
> > internal ? openlog (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog
> > (6, "%s", STR("Doing internal stuff\n"));closelog (); : openlog
> > (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog (6, "%s", STR("Not
> > internal stuff\n"));closelog ();;

>
> To answer your original question:
>
> What's wrong with the macro is that it is three statements, and you
> use it in a context where only an expression is required.
> Solution: Don't do that.
>
> You probably want to use the well-known trick do create a macro that
> is a single statement without semicolon like:
>
> #define LOG (level, msg) do { whatever (); } while (0)
>
> and get rid of that rubbish where you use a ternary operator to save
> an if statement, which is just rubbish and demonstrates that someone
> tries to look clever without actually being clever. Or change the
> #define so that the macro is an actual expression.


Thanks for all your replies!

Brs,
Markus
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-15-2012
dspfun <(E-Mail Removed)> writes:

> Can you see anything wrong or "bad" with the following macro?
>
> #define LOG(level, msg) \
> openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> \
> syslog (level, "%s", msg);\
> closelog ();
>
> I have problems using the macro with ternary operators. I believe it
> should have parantheses around it all, but I cannot get it right.


If you want the macro to be usable *as a statement*, you
should use the do ... while (0) trick; see question 10.4
in the comp.lang.c FAQ, http://c-faq.com/. Each occurrence
of any parameter name in the macro should be in parentheses.
See <https://github.com/Keith-S-Thompson/42> for an example of what
can happen if you don't follow this rule.

If you need to to be usable *as an expression*, you can't use
do/while -- but you can use the comma operator. In addition to
parenthesizing each parameter reference, the entire definition
should be enclosed in parentheses.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      01-15-2012
On 01/16/12 02:29 AM, dspfun wrote:
> Hi all!
>
> Can you see anything wrong or "bad" with the following macro?
>
> #define LOG(level, msg) \
> openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> \
> syslog (level, "%s", msg);\
> closelog ();
>
> I have problems using the macro with ternary operators. I believe it
> should have parantheses around it all, but I cannot get it right.


Reduce the macro to a simple function call:

void log( const char* func, int level, const char* msg )
{
openlog( func, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER );
syslog( level, "%s", msg );
closelog();
}

#define LOG(level, msg) log( __func__, level, msg )

Why do people insist on making extra work for them selves by trying to
write overly complex macros were a function will do the job?

--
Ian Collins
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      01-16-2012
dspfun wrote:
> On 15 Jan, 15:37, "christian.bau" wrote:
> > On Jan 15, 1:58*pm, dspfun wrote:
> > > On 15 Jan, 14:44, Dr Nick wrote:
> > > > dspfun <(E-Mail Removed)> writes:
> > > > > Can you see anything wrong or "bad" with the following macro?
> > > > > #define LOG(level, msg) \
> > > > > openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> > > > > \
> > > > > syslog (level, "%s", msg);\
> > > > > closelog ();

> >
> > > > > I have problems using the macro with ternary operators. I believe it
> > > > > should have parantheses around it all, but I cannot get it right.

> >
> > > > Do you mean using it inside operators - like:

> >
> > > > b==c ? LOG(10,"hello") : LOG(2,"goodbye");

> >
> > > > If so, then you will have problems as the macro is three statements while
> > > > the ternary operator expects a single expression on each side.

> >
> > > > If you do want to use it with an if you need to be careful to wrap it in
> > > > {}s. *You might want to use the do{ ... } while(0) trick.

> >
> > > Here is the function/code where it is used (slightly modified, but
> > > still is valid):

> >
> > > static void
> > > foo(Boolean internal)
> > > internal ? TRACE_IF(8, STR("Doing internal stuff\n")) : TRACE_IF(8,
> > > STR("Not internal stuff\n"));
> > > ..snip...

> >
> > > TRACE_IF is defined as:

> >
> > > #define TRACE_IF(GROUP,MSG) LOG(LOG_INFO, MSG)

> >
> > > LOG is defined as:
> > > #define LOG(level,msg) openlog (__FUNCTION__, LOG_CONS | LOG_PID |
> > > LOG_NDELAY, LOG_USER); syslog (level, "%s", msg);closelog ();

> >
> > > Resulting in:

> >
> > > internal ? openlog (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog
> > > (6, "%s", STR("Doing internal stuff\n"));closelog (); : openlog
> > > (__FUNCTION__, 0x02 | 0x01 | 0x08, (1<<3)); syslog (6, "%s", STR("Not
> > > internal stuff\n"));closelog ();;

> >
> > To answer your original question:
> >
> > What's wrong with the macro is that it is three statements, and you
> > use it in a context where only an expression is required.
> > Solution: Don't do that.
> >
> > You probably want to use the well-known trick do create a macro that
> > is a single statement without semicolon like:
> >
> > #define LOG (level, msg) do { whatever (); } while (0)
> >
> > and get rid of that rubbish where you use a ternary operator to save
> > an if statement, which is just rubbish and demonstrates that someone
> > tries to look clever without actually being clever. Or change the
> > #define so that the macro is an actual expression.


I respectfully disagree with the suggestion to put do ... while (0)
around this macro. In my experience, a macro should always be written as
an expression if it can be. In the example from the OP, there is no
reason whatsoever to write it as a statement--all that is required to
write it as an expression is to substitute commas for the semicolons and
enclose the whole thing in parentheses.

However, I do agree with the advice to avoid the ternary operator and
use an if statement. (Unless, of course, the ternary operator is within
another macro, in which case refer to the above paragraph.)

The do ... while (0) idiom is great when the macro cannot be written as
an expression.

And one final thing: are you *sure* you want to open and close the log
for every trace message?

Philip
 
Reply With Quote
 
Philip Lantz
Guest
Posts: n/a
 
      01-16-2012
Ian Collins wrote:
>
> On 01/16/12 02:29 AM, dspfun wrote:
> > Hi all!
> >
> > Can you see anything wrong or "bad" with the following macro?
> >
> > #define LOG(level, msg) \
> > openlog (__FUNCTION__, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER);
> > \
> > syslog (level, "%s", msg);\
> > closelog ();
> >
> > I have problems using the macro with ternary operators. I believe it
> > should have parantheses around it all, but I cannot get it right.

>
> Reduce the macro to a simple function call:
>
> void log( const char* func, int level, const char* msg )
> {
> openlog( func, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER );
> syslog( level, "%s", msg );
> closelog();
> }
>
> #define LOG(level, msg) log( __func__, level, msg )
>
> Why do people insist on making extra work for them selves by trying to
> write overly complex macros were a function will do the job?


Oh, good point! I shoulda read the whole thread before I sent my
response.

Philip
 
Reply With Quote
 
Nick Keighley
Guest
Posts: n/a
 
      01-16-2012
On Jan 16, 1:30*am, Philip Lantz <(E-Mail Removed)> wrote:

> And one final thing: are you *sure* you want to open and close the log
> for every trace message?


1. you can read the logfile on a Windows system while the system is
running
2. if the system crashes you get all the trace messages

you could bundle trace messages and write them out, say, every second
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dedicated Macro or Normal Macro? John Ortt Digital Photography 5 11-22-2005 12:43 PM
Macro lens on a camera with a macro setting??? mitchell.chris@gmail.com Digital Photography 2 09-28-2005 07:55 AM
in S.E. Asia : Canon EOS 300d with 100 macro ED vs. Nikon D70 with Nikon 105 macro ? J. Cod Digital Photography 0 09-29-2004 05:46 AM
#define macro to enclose an older macro with strings Dead RAM C++ 20 07-14-2004 10:58 AM
macro name from macro? D Senthil Kumar C Programming 1 09-21-2003 07:02 PM



Advertisments