inline functions vs. macros

R

Robert Seacord

When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?

What sort of things is it still reasonable to do using macros? For
example, is it reasonable to write type generic functions macros?

#define CUBE(I) ( (I) * (I) * (I) )

Is there some more concise set of things where inline functions should
be used instead of macros? Multi-statement macros, for example?

Thanks,
rCs
 
B

Ben Pfaff

Robert Seacord said:
Is there some more concise set of things where inline functions should
be used instead of macros? Multi-statement macros, for example?

In general, if an inline function can be used, it should be
used. Inline functions are much less likely to cause nasty
surprises than macros, so they are preferred.
 
D

Darko

Well, as the majority probably know, macros are really tricky to use
and one should be very careful with them. The best example I know when
they shouldn't be used, is the following:

#define max(a,b) ((a)>(b)?(a):(b))
int x = 4, y = 5;
int z = max(x++, y++);

One would expect the x and y to be incremented once each, but the fact
is the text renders into the following:
int z = ((x++)>(y++)?(x++):(y++)),
which means the bigger of the two will get incremented twice instead of
only once.
 
A

Andrey Tarasevich

Robert said:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?

In cases when the both methods are interchangeable - of course, using inline
functions is a better idea.
What sort of things is it still reasonable to do using macros?

There are lots of things that can only be done with macros. Macros can be used
as a substitute for absolutely any piece of code and that means a lot.

For example, one can use macros to generate object and function declarations and
definitions. One can use macros to implement "local functions" (repetitive
pieces of code that have access to automatic variables from the enclosing
scope). Functionality of macros can be used to simulate functionality of
templates in C++.

When macros are used to implement "functions" they can be made to support
certain form of "lazy calculation". For example, the following macro

#define SELECT(s, v1, v2) ((s) ? (v1) : (v2))

will calculate only one of the two expressions depending on the selector's value
(cannot be achieved with an inline function).

And so on. Again, there are lots of other things that can only be done with
macros. One just have to keep in mind that benefits of macros often come with a
considerable number of drawbacks, meaning that one has to use macros with
caution. Nevertheless, the popular belief that macros should be avoided at all
costs makes absolutely no sense. But in situations where macros and inline
functions offer the same functionality it is better to stick with inline functions.
For
example, is it reasonable to write type generic functions macros?

#define CUBE(I) ( (I) * (I) * (I) )

Well, if the key point here is to have a type-generic "function", then it is
reasonable. However, in a simple case like this it might prove to be a better
decision to just write several inline functions with different names. Actually,
macros can still be used to do the latter as shown below:

#define DEFINE_CUBE(T, s) inline T cube_##s(T v) { return v * v * v; }

DEFINE_CUBE(double, d)
DEFINE_CUBE(int, i)
DEFINE_CUBE(unsigned, ui)
 
R

Richard Heathfield

Darko said:
Well, as the majority probably know, macros are really tricky to use

I agree that macros do require a modicum of care, particularly if their
arguments are evaluated more than once, but I wouldn't go so far as to say
they're really tricky. Yes, okay, you can /make/ them tricky, but then you
can make functions tricky, too.
 
A

Ancient_Hacker

Robert said:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?

They're apples versus kittens. About all they have in common is
they're both edible.

With a macro you're assured it's going to get expanded as text right
there. Now is it assured an inline function will get expanded inline?

With a macro you can call it in any context, with or without parens,
and it will generate almost any syntactical mess. A function can only
be used in certain contexts, executable, and must have parens.

macros have their place when you need some bizarre declaration or
executable code.
For instance since C doesnt have a "with" statement, you have to write:

Application->WindowList[ Message->WindowIndex ]->Next->Panel->Title =
"syph";
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Font =
"Aramaic";
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Style =
S_BOLD;
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Align=
AA_RIGHT;

.... which just cries out for some factoring. One way is to (ouch) use
a macro.
 
J

John Bode

Robert said:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?

What sort of things is it still reasonable to do using macros? For
example, is it reasonable to write type generic functions macros?

#define CUBE(I) ( (I) * (I) * (I) )

It is, until someone innocently writes

x = CUBE(y++);

and gets undefined behavior for their trouble.
Is there some more concise set of things where inline functions should
be used instead of macros? Multi-statement macros, for example?

Thanks,
rCs

Remember that the C preprocessor is strictly a text substitution
mechanism; it does not know or care about scope, or type, or syntax, or
anything else. Therefore, using preprocessor macros to simulate inline
functions or to fake generic programming is generally a bad idea for
anything other than the most simple of expressions, and even then you
have to beware of situations like the one I describe above.

If you need a function-like operation, then use an actual function,
whether it's inline or not. If you're concerned about efficiency, use
a profiling tool to find the real bottlenecks; don't just blindly
convert functions to macros in the hopes that it will speed things up.

If you want generics, use C++ or some other language that supports
them. Trying to fake it in C is often more trouble than it's worth.
 
I

Ian Collins

Ancient_Hacker said:
Robert said:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?


They're apples versus kittens. About all they have in common is
they're both edible.

With a macro you're assured it's going to get expanded as text right
there. Now is it assured an inline function will get expanded inline?

With a macro you can call it in any context, with or without parens,
and it will generate almost any syntactical mess. A function can only
be used in certain contexts, executable, and must have parens.

macros have their place when you need some bizarre declaration or
executable code.
For instance since C doesnt have a "with" statement, you have to write:

Application->WindowList[ Message->WindowIndex ]->Next->Panel->Title =
"syph";
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Font =
"Aramaic";
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Style =
S_BOLD;
Application->WindowList[ Message->WindowIndex ]->Next->Panel->Align=
AA_RIGHT;

.... which just cries out for some factoring. One way is to (ouch) use
a macro.
Or
PanelType *panel =
&Application->WindowList[Message->WindowIndex]->Next->Panel;
 
F

Frederick Gotham

Robert Seacord posted:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?


Not in general, no, for three reasons:

(1) C90 doesn't support inline.
(2) Even if the compiler _does_ support inline, the code is guaranteed to
be inlined.
(3) It doesn't yield a compile-time constant.

What sort of things is it still reasonable to do using macros? For
example, is it reasonable to write type generic functions macros?


Yes, it's grand.

#define CUBE(I) ( (I) * (I) * (I) )


This one evaluates its argument more than once, but that's OK since the
macro name is in ALL CAPS, which serves as a warning to the programmer.

Is there some more concise set of things where inline functions should
be used instead of macros? Multi-statement macros, for example?


If you need to define variables _and_ return a value, you might need a
function.
 
C

Christopher Benson-Manica

Frederick Gotham said:
(1) C90 doesn't support inline.
(2) Even if the compiler _does_ support inline, the code is guaranteed to
^^ isn't
be inlined.
(3) It doesn't yield a compile-time constant.

A macro might not either; much good and evil can be done with macros.
 
A

Andrew Poelstra

Robert Seacord posted:

Not in general, no, for three reasons:

(1) C90 doesn't support inline.
(2) Even if the compiler _does_ support inline, the code is guaranteed to
be inlined.

You meant /not/ guaranteed to be inline. According to C99, that is.
 
P

Pedro Graca

Darko top-posted [reordered]:
Well, as the majority probably know, macros are really tricky to use
and one should be very careful with them. The best example I know when
they shouldn't be used, is the following:

#define max(a,b) ((a)>(b)?(a):(b))
int x = 4, y = 5;
int z = max(x++, y++);

One would expect the x and y to be incremented once each, but the fact
is the text renders into the following:
int z = ((x++)>(y++)?(x++):(y++)),
which means the bigger of the two will get incremented twice instead of
only once.

And if you had defined your macro in ALL UPPERCASE, someone writing

int z = MAX(x++ .... hey! it's MAX in all uppercase
.... must be a macro, let me do it like this instead

x++; y++;
int z = MAX(x, y); /* wheew! good thing the original programmer
used ALL UPPERCASE for this macro :) */
 
W

websnarf

Robert said:
When writing C99 code is a reasonable recommendation to use inline
functions instead of macros?

For the purposes of portability or long term viability/maintainability,
use of C99 is *not* a reasonable recommendation. You should use C
compilers that will have long term support, or otherwise write code to
the lowest common denominator (portable C/C++.)

Keep in mind that "static" function declarations are usually basically
equivalent to what is intended by C99's "inline". For serious
compilers, there should be no effective difference between the two
(inline further asserts that taking the address of the function is
illegal, however, a static function whose address *isn't* taken (which
it can always determine because it *is* static) becomes equivalent in
functional status.)
What sort of things is it still reasonable to do using macros? For
example, is it reasonable to write type generic functions macros?

#define CUBE(I) ( (I) * (I) * (I) )

Is there some more concise set of things where inline functions should
be used instead of macros?

The general rule of thumb that I use is that complicated macros should
be module local and commented (or obvious). Otherwise, macros should
be limited to constants, or convenience wrappers.
Multi-statement macros, for example?

There's the whole issue of if() else and multi-line macros. The way
you can get around it is to wrap your multi-line macro with a do { ...
} while(0);. Unfortunately many compilers complain that the while (0)
condition is constant and issue a warning. I don't like turning this
warning off in the compiler, because its reasonable if the "0" comes
from some compiler simplifications. So we're kind of in a no-win
scenario here.

Sometimes some kinds of multi-statement macros can lead to interesting
conundrons. Suppose we have the following macro:

#define hf_idxFirst(t,i) {\
i = hf_NOT_FOUND;\
if (NULL != (t)) hf_idxNext(t,i);\
}

This is fine, except that you cannot write code such as this:

for (hf_idxFirst (table, i); !hf_idxIsEnd(table,i);
hf_idxNext(table,i)) {
/* ... */
}

This isn't so much a multi-statement macro issue as much as a control
code fragment limitation issue that gets hidden by a macro.
 
K

Keith Thompson

Keep in mind that "static" function declarations are usually basically
equivalent to what is intended by C99's "inline". For serious
compilers, there should be no effective difference between the two
(inline further asserts that taking the address of the function is
illegal, however, a static function whose address *isn't* taken (which
it can always determine because it *is* static) becomes equivalent in
functional status.)

I believe it's perfectly legal to take the address of an inline
function. Can you cite something in the standard that says otherwise?
In particular, the function call operator expects a
pointer-to-function, so just calling a function implicitly takes its
address.

(The standard *could* have said that taking the address of an inline
function other than in a direct call is illegal, but it doesn't.)
 
A

Andrey Tarasevich

...
inline further asserts that taking the address of the function is
illegal
...

That's incorrect. There's absolutely nothing illegal in taking the address of an
inline function.
 
I

Ian Collins

Frederick said:
Robert Seacord posted:





Not in general, no, for three reasons:

(1) C90 doesn't support inline.

The OP asked about C99.
(2) Even if the compiler _does_ support inline, the code is guaranteed to
be inlined.
(3) It doesn't yield a compile-time constant.
?
 
R

Richard Heathfield

Ian Collins said:
The OP asked about C99.

Nevertheless, it's a reasonable point. When writing C99 code, it is for the
time being (and, the way, we're going, for the foreseeable future too)
reasonable to keep the code portable to C90, unless one is prepared to
forego the advantages thereof.

I'm not sure what he means by that, either.
 
R

Richard Heathfield

Andrew Poelstra said:
You meant /not/ guaranteed to be inline. According to C99, that is.

I am fairly sure he meant something like "[the macro version of] the code is
*guaranteed* to be inlined".
 
I

Ian Collins

Richard said:
Ian Collins said:




Nevertheless, it's a reasonable point. When writing C99 code, it is for the
time being (and, the way, we're going, for the foreseeable future too)
reasonable to keep the code portable to C90, unless one is prepared to
forego the advantages thereof.
True, which brings us back to the old dilemma of pragmatism or
portability. I think every recent (last 10 years) C compiler I've used
either supports inline as an extension, or inlines as an optimisation,
or both.
 
R

Richard Heathfield

Ian Collins said:
Richard Heathfield wrote:
[...]
When writing C99 code, it is for
the time being (and, the way, we're going, for the foreseeable future
too) reasonable to keep the code portable to C90, unless one is prepared
to forego the advantages thereof.
True, which brings us back to the old dilemma of pragmatism or
portability.

For me, portability is part of pragmatism.

And so, of course, is non-portability.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Endianness macros 48
C Programming functions 2
inline functions 50
inline function vs function-like macro 2
Variadic debug macros 5
inline vs. function pointers 36
Generating functions with Macros in Perl 6
macros 2

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top