Re: Is it better to use a macro or a function?
- From: Johan Bengtsson <qwerty_42@xxxxxxxxxxx>
- Date: Thu, 07 Jun 2007 20:20:21 GMT
Ben Pfaff wrote:
madhawi <madhawi.k@xxxxxxxxx> writes:
Is it better to use a macro or a function?
Some tasks can only be accomplished with a macro. Otherwise, use
a function: in general, they're safer.
An example:
I have in some of my programs a lot of pointers to structs.
struct a
{
char *s1;
char *s2
} *b;
char *s;
A general problem then is that such a pointer might be NULL and therefore referencing a member of that struct is illegal.
s=b->s1; /*if b is NULL this doesn't work well...*/
Now if what I want is something like this:
if (b)
s=b->s1;
else
s=NULL;
That is I want to assign *something* to s, if b is NULL (or for that matter b->s1 is NULL) I do want s to be NULL too. This could be written:
s=b?b->s1:NULL;
That's OK, so know if b isn't really a variable but rather a long complex expression I need to type that twice to get the desired effect.
#define spt(ptr)(!(ptr))?NULL:ptr
would make it possible to write
s=spt(b)->s1;
That trick is *not* possible with a function!
Oh, and before someone points it out, it is not entirely safe either, an expression in the place of b with side effects would not do what is intended! But it have helped me write some shorter and more (IMO) readable code. The expression b is evaluated twice if it is non-NULL, but as long as it doesn't have side effects and there is no speed requirements or the compiler is good enough at optimizing that doesn't matter.
It is even possible to chain them like this (obviously with some other declarations necessary)
res=spt(spt(spt(ptr)->member)->member)->member;
This allows for every step to be NULL and expands to (line breaks inserted for readability):
res=(!((!((!(ptr))?NULL:ptr->member))?NULL:(!(ptr))?NULL:
ptr->member->member))?NULL:(!((!(ptr))?NULL:ptr->member))?NULL:
(!(ptr))?NULL:ptr->member->member->member;
and doing exactly what I want but much more readable with the macro
than without. Of course typing
if (ptr)
{
if (ptr->member)
{
if (ptr->member->member)
res=ptr->member->member->member;
else
res=NULL;
}
else
res=NULL;
}
else
res=NULL;
would also produce the same result but would not (again IMO) be as readable.
Oh, once again, don't try this at home unless you understand the restriction "expression *must* be without side effects"
.
- Follow-Ups:
- Re: Is it better to use a macro or a function?
- From: Numeromancer
- Re: Is it better to use a macro or a function?
- From: Ben Bacarisse
- Re: Is it better to use a macro or a function?
- References:
- Is it better to use a macro or a function?
- From: madhawi
- Re: Is it better to use a macro or a function?
- From: Ben Pfaff
- Is it better to use a macro or a function?
- Prev by Date: How to make a LAN scanner
- Next by Date: generate variable names
- Previous by thread: Re: Is it better to use a macro or a function?
- Next by thread: Re: Is it better to use a macro or a function?
- Index(es):
Relevant Pages
|
|