#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0);
now, of course this will work but how is this any better than:
#define CALL_FUNCS(x) \
{ \
func1(x); \
func2(x); \
func3(x); \
}
i can't see how the compiler can optimize (a) any better than (b) or in
any case can (b) break what (a) won't. Any input will be appreciated.
tia
Yan a écrit :
> A lot of times when reading open software, i come across macros that are
> defined as follows:
>
> #define CALL_FUNCS(x) \
> do { \
> func1(x); \
> func2(x); \
> func3(x); \
> } while (0);
are you sure there is ";" at the end ?
because I thought the reason why you use "do { } while(0)" is this ";" !
you don't have to put it there, and I explain why after...
>
> now, of course this will work but how is this any better than:
>
> #define CALL_FUNCS(x) \
> { \
> func1(x); \
> func2(x); \
> func3(x); \
> }
>
> i can't see how the compiler can optimize (a) any better than (b) or in
> any case can (b) break what (a) won't. Any input will be appreciated.
you should see where it's used in the code, and then you will understand !
in the code you will find this :
...
CALL_FUNCS(12); /* becareful of this ";" */
...
so the preprocessor will replace CALL_FUNCS(12) by :
(a)
...
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0); /* <- this ";" will end do { } while(0) in good way */
...
(b)
...
{ \
func1(12); \
func2(12); \
func3(12); \
}; /* <- too much ";" */
...
Maybe there is another reason, but I'm sure I read this explanation
somewhere (maybe here).
Alexandre
--
"That's what they should teach us here", he (Harry Potter) thought, ...,
"how's girls' brains work ... it'd be more useful than Divination, anyway
..."
Harry Potter and the Order of the Phoenix
J.K. Rowling
> A lot of times when reading open software, i come across macros that
> are defined as follows:
>
> #define CALL_FUNCS(x) \
> do { \
> func1(x); \
> func2(x); \
> func3(x); \
> } while (0);
Read the FAQ.
--
Ben Pfaff
email: b...@cs.stanford.edu
web: http://benpfaff.org
It is not about optimization.
The whole idea of using 'do/while' version is to make a macro which will
expand into a regular statement, not into a compound statement. This is
done in order to make the use of function-style macros uniform with the
use of ordinary functions in all contexts.
Consider the following code sketch
if (<condition>)
foo(a);
else
bar(a);
where 'foo' and 'bar' are ordinary functions. Now imagine that you'd
like to replace function 'foo' with a macro of the above nature
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
Now, if your macro is defined in accordance with the second approach
(just '{' and '}') the code will no longer compile, because the 'true'
branch of 'i' is now represented by a compound statement. And when you
put a ';' after this compound statement, you finished the whole 'if'
statement, thus orphaning the 'else' branch (hence the compilation error).
One way to correct this problem is to remember not to put ';' after
macro "invocations"
if (<condition>)
CALL_FUNCS(a)
else
bar(a);
This will compile and work as expected, but this is not uniform. The
more elegant solution is to make sure that macro expand into a regular
statement, not into a compound one. One way to achieve that is to define
the macro as follows
#define CALL_FUNCS(x) \
do { \
func1(x); \
func2(x); \
func3(x); \
} while (0)
Now this code
if (<condition>)
CALL_FUNCS(a);
else
bar(a);
will compile without any problems.
However, note the small but important difference between my definition
of 'CALL_FUNCS' and the first version in your message. I didn't put a
';' after '} while (0)'. Putting a ';' at the end of that definition
would immediately defeat the entire point of using 'do/while' and make
that macro pretty much equivalent to the compound-statement version.
I don't know why the author of the code you quoted in your original
message put this ';' after 'while (0)'. In this form both variants are
equivalent. The whole idea behind using 'do/while' version is not to
include this final ';' into the macro (for the reasons that I explained
above).
--
Best regards,
Andrey Tarasevich
> Yan writes:
>
>>A lot of times when reading open software,
>>I come across macros that are defined as follows:
>>
>>#define CALL_FUNCS(x) \
>>do { \
>> func1(x); \
>> func2(x); \
>> func3(x); \
>>} while (0);
>
> Read the FAQ.
Could you please cite and quote the FAQ
that is relevant to this question?
-Adam Roan
"Just plain neat."
I used Google
to search for
"comp.lang.c faq multi-statement"
and the 1st link showed the FAQ # to be 10.4
> A lot of times when reading open software,
> I come across macros that are defined as follows:
>
> #define CALL_FUNCS(x) \
> do { \
> func1(x); \
> func2(x); \
> func3(x); \
> } while (0);
This practice is obsolete and should be discouraged.
Write inline function definitions instead:
inline static
void CALL_FUNCS(double x) {
func1(x);
func2(x);
func3(x);
}
Try things like:
if (cond)
CALL_FUNCS(a);
else
CALL_FUNCS(b);
and see how far you get.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
It's a common C idiom that all C programmers should be familiar with.
If you find it annoying -- well, it's not the worst annoyance in the
language.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
That's great if you happen to have a compiler that supports inline
function definitions *and* you're not concerned about your code being
ported to a compiler that doesn't. You might have that luxury. Don't
assume that everyone else does.
I strongly disagree. There are certainly many cases where
the approach is best.
Consider this example
#define CALL_FUNC(x, y, z) \
do { \
x##_fun1(y, #z); \
x##_fun2(y, #z); \
x##_fun3(y, #z); \
} while(0)
Now let how do you propose an inline function can handle
this common sort of construct?
By all counts, inline functions don't quite cut it for this situation.
An inline function has to assume a specific datatype for all use
of the macro, which somewhat restricts the input, and somewhat
defeats major advantages of using macros.
like
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Is more general than
double max(double a, double b) { return a > b ? a : b; }
The latter treats everything as a double.
i.e. if you called max() on two ints... you get totally unnecessary
conversions from int to double
> That's great if you happen to have a compiler
> that supports inline function definitions
> *and* you're not concerned about your code being ported to a compiler that doesn't.
> You might have that luxury. Don't assume that everyone else does.
I cordially invite and welcome all comp.lang.c subscribers
to come on into the twenty first century.
http://www.eskimo.com/~scs/C-faq/q10.4.html
Now why don't *you* read the FAQ.
Oh yes, I remember now, you are a troll, that's why you don't read the FAQ.
This is certainely not what you have seen. Read again, it is more
likely:
} while (0)
and it's precisely the point.
> #define CALL_FUNCS(x) \
> { \
> func1(x); \
> func2(x); \
> func3(x); \
> }
>
> i can't see how the compiler can optimize (a) any better than (b) or in any
> case can (b) break what (a) won't. Any input will be appreciated.
It's not a question of optimization, but it's the only non invasive
known trick that forces the user to put a ';' after the macro usage,
making the syntax consistent.
Nothing else.
--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html
"C is a sharp tool"
Your are correct in theory, but the C-compilers installed on zillions
of machines across the world and not magically going to switch to C99
just because a new release of the language came out...
--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html
"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.
>An inline function has to assume a specific datatype for all use
>of the macro, which somewhat restricts the input, and somewhat
>defeats major advantages of using macros.
>
>like
>#define MAX(a, b) ((a) > (b) ? (a) : (b))
>Is more general than
>
>double max(double a, double b) { return a > b ? a : b; }
>
>The latter treats everything as a double.
>i.e. if you called max() on two ints... you get totally unnecessary
>conversions from int to double
If you use the macro MAX(a++, b), you'd invoke fairly undefined behaviour
with one of the expressions being evaluated twice.
A C-programmer fitted with a working brain won't write that.
--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html
"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
By that argument we should all still be writing in K&R C instead of C89; one
must draw a line somewhere, and it's perfectly valid in many cases to make
it C99 (or C89 with very common extensions).
S
--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin
As far as I know, there are very few platforms with an available K&R C
compiler but no available C89/C90 compiler. I understand that Recent
releases of gcc, for example, assume that the hosting compiler is C90
compliant.
On the other hand, there are still plenty of platforms with no
available C99 compiler. I'd be very pleasantly surprised to discover
that that's not the case.
> There are still plenty of platforms with no available C99 compiler.
Can you enumerate them?
The GNU C compiler ports almost everywhere
and is pretty near C99 compliant.
>On 30 Dec 2004 19:32:31 -0800, "Mysidia" <mys...@gmail.com> wrote:
>
>>#define MAX(a, b) ((a) > (b) ? (a) : (b))
>
>If you use the macro MAX(a++, b), you'd invoke fairly undefined behaviour
As opposed to unfairly defined? :)
>with one of the expressions being evaluated twice.
There's a sequence point between the two.
-- Mat.
Nope.
> The GNU C compiler ports almost everywhere
> and is pretty near C99 compliant.
"Almost" and "pretty near" aren't good enough for everyone's purposes.
I know gcc supports all the C99 features that *you* care about, but
that's relevant only to you.
> E. Robert Tisdale writes:
>
>>The GNU C compiler ports almost everywhere
>>and is pretty near C99 compliant.
>
> "Almost" and "pretty near" aren't good enough for everyone's purposes.
Nonsense!
They are good enough for C90 programmers.
C programmers accepted the new C90 standard
long before it was as mature as the C99 standard is now.
I don't see why they should hold C99 to a higher standard than C90.
Do you?
The issue isn't the maturity of the standard, it's how widespread
conforming implementations are. When C90 implementations were in the
state that C99 implementations are now, C90 code (particularly code
using function prototypes) still had to be considered non-portable.
It was still common to use preprocessor tricks to allow code to
compile both under K&R and C90 compilers. There was (and still is) a
tool called "ansi2knr" which translated C90 code to K&R code.
Some users were lucky enough to work in environments were they didn't
have to be concerned about portability to pre-C90 compilers, but most
of them were sensible enough not to berate those who weren't.
That a common implementation is not quite compliant isn't justification for
not using language features where it is compliant. I'm sure one can find
examples where GCC isn't C90 compliant either; should we go back to K&R C
until GCC is fixed?
> > Nonsense!
> >
> > They are good enough for C90 programmers.
> > C programmers accepted the new C90 standard
> > long before it was as mature as the C99 standard is now.
> > I don't see why they should hold C99 to a higher standard than C90.
> > Do you?
>
> The issue isn't the maturity of the standard, it's how widespread
> conforming implementations are. When C90 implementations were in the
> state that C99 implementations are now, C90 code (particularly code
> using function prototypes) still had to be considered non-portable.
> It was still common to use preprocessor tricks to allow code to
> compile both under K&R and C90 compilers. There was (and still is) a
> tool called "ansi2knr" which translated C90 code to K&R code.
The situation is different in this case, though, since most of the changes
in C99 were already typically implemented as extensions to C90 compilers.
> Some users were lucky enough to work in environments were they didn't
> have to be concerned about portability to pre-C90 compilers, but most
> of them were sensible enough not to berate those who weren't.
I don't berate those using C90 (or K&R) compilers because I know there are
often reasons that users don't have a choice. However, I do think it's
reasonable to code to C99 these days; the changes are minor enough that
anyone interested can back-port the code and submit patches.
> "Emmanuel Delahaye" <em...@YOURBRAnoos.fr> wrote in message
> news:mn.fa7d7d4cc...@YOURBRAnoos.fr...
>> Your are correct in theory, but the C-compilers installed on zillions
>> of machines across the world and not magically going to switch to C99
>> just because a new release of the language came out...
>
> By that argument we should all still be writing in K&R C instead of C89; one
> must draw a line somewhere, and it's perfectly valid in many cases to make
> it C99 (or C89 with very common extensions).
It's perfectly valid in many cases to assume GCC with its extensions
(indeed, much of my code has done), or in other cases to assume that you
have a POSIX comlpiant library (a fair bit of my code assumes that),
etc. However, if you need to make your code maximally portable you need
to assume the minimum standard. This is why a fair bit of code still
uses compiler tricks for function prototypes, because there are still
some systems with only K&R1 compilers (as I recall the compiler supplied
on SunOS systems was barely K&R, it just sufficed to compile GCC but
probably wouldn't even do that with recent versions of GCC). In
practice, assuming C89 is pretty safe by now (15 years after the
standard came out).
There are a number of extensions in C99 which I would like to use, but
can't until C99 compilers get a lot more common (in particular GCC is
still not fully C99 compliant, in particular some of the functions and
headers have chunks of "not implemented yet" in them).
Not everyone has the choice of what compiler they use, many places won't
allow other software to be insttalled (and even when they do there is no
point in one person using a C99 compiler when the rest of the company is
using a C89 one and the code is required to be used by others!). I
doubt if many places are still using a pre-C89 compiler for any serious
development, but I know of none who are using a fully-compliant C99
compiler (indeed, from recent discussions here it seems that there isn't
one yet apart from possibly Comeau/Dinkumware, but their website says
only that it is "as close as you can get to full compliance", not that
it is fully compliant).
Chris C
Will you never stop?