What is the gain of "inline"

T

Tom St Denis

Yes, often simple functions can be implemented as macros.  I'm
advocating that they not be implemented as macros, because macros
have too many well-known pitfalls, that you surely are aware of.
You are advocating the opposite, but it isn't clear why.  Why?
Assuming you wrap your macro with the appropriate do { } while (0)
style brace it should fit anywhere you don't need a return code.
I'm against putting code in a header file because it's just messy and
usually leads to disorganized code trees. [...]
Why would putting an inline function in a header file cause the
tree to be more disorganized than putting an equivalent macro in
the header file?  I can see how an excess of either one could
cause problems, but I don't see how either one would cause more
disorganization than the other.
Because it's just not where code should go.  

I see ... and a Macro is not code because .. ??

Develop code how you want. I don't give a rats ass really. I'm
trying to offer some helpful advice from my experience as a software
developer. You're too prideful to either accept it or just graciously
decline it is YOUR OWN PROBLEM.

I'm not going to reply to you again in this thread.

Tom
 
T

Tom St Denis

Macros that stand in for C functions are not traditionally written in
upper case.

E.g. getc in a traditional implementation of the C library.

A lot of those were at one point functions.

As a general rule of thumb defines/macros should be uppercase, it
makes reading code a lot easier.
Really; not a single thing worse, Tom?

Well, there was the snow storm yesterday, that was pretty bad. But
I'd say trying to debug a clusterfark of poorly written code on a
deadline to be a stress I don't particularly enjoy...
No grep? No ctags? No mkid? No cscope?

You clearly have no comprehension of #ifdef hell.
Inline functions provide safety over macros.

How about not perform unsafe casts?
 /* this converts only ``bar *'' arguments to foo *.
    If you want to abuse it, you have to write the cast
    at the call site. */

 inline foo *the_foo(bar *b) { return (foo *) b; }

Why the hell would you do that? You can't dereference what the return
type points to unless "bar" is void *.

Another reason not to use inline functions: compilation speed.

I'll forever be confused to why Dane Cook is popular, or how Jack
Black has a movie career, but most of all, why people think it's
impressive to brag about a million lines of code and 8 hour build
times for what should be relatively simple applications.

Tom
 
B

Ben Pfaff

Tom St Denis said:
Because it's just not where code should go. It also means any file
that includes that file runs the chance of including the inlined code,
wasting space.

No decent compiler will do that.
When I want to look for a function, it should be in a .c file
in a well sorted directory structure.

"tags" does a fine job of finding functions regardless of where
they are defined.
Those are all one-liners which are perfectly well suited for being
macros.

No, not at all. For example, the following inline function
cannot be implemented as a macro (in an obvious way, at least)
without evaluating its argument more than once:

static inline bool ovsdb_type_is_set(const struct ovsdb_type *type)
{
return (type->value_type == OVSDB_TYPE_VOID
&& (type->n_min != 1 || type->n_max != 1));
}
Why is

static inline int foo(int a) { return a + 3; }

So much simpler than

#define FOO(a) ((a) + 3)

?

Because the properties of a C function are much more predictable
than the properties of a C macro. For example, when foo is
defined as a function, the argument type and return type are
well-defined.
 
K

Keith Thompson

Tom St Denis said:
You obviously haven't worked on highly configurable code before. It's
not uncommon to have platform specific branches of code that include
platform specific macros.

Ok, say you have "250 unsorted .c and .h files" in a moderately
complex directory tree, and you're trying to find the declaration
of SomeFunction. A textual search of all the files (or just of
all the *.h files) for "SomeFunction", using grep or your system's
equivalent, should at least narrow the search down to a very small
number of files. I do similar things on a much larger code base
(though without a whole lot of multi-platform configurability),
and it works reasonably well unless it's a name that's used
multiple times.
 
T

Tom St Denis

No, not at all.  For example, the following inline function
cannot be implemented as a macro (in an obvious way, at least)
without evaluating its argument more than once:

    static inline bool ovsdb_type_is_set(const struct ovsdb_type *type)
    {
        return (type->value_type == OVSDB_TYPE_VOID
                && (type->n_min != 1 || type->n_max != 1));
    }

Ok, but here's the question. What is the performance hit of this
being a normal function vs. inline? Is it actually called enough to
warrant this behaviour?
Because the properties of a C function are much more predictable
than the properties of a C macro.  For example, when foo is
defined as a function, the argument type and return type are
well-defined.

Perhaps, I see what you're saying. But if it's not a performance
hazard who cares if the function is small, don't inline it.

Tom
 
W

Willem

Tom St Denis wrote:
)> So why are you not against putting code in header files,
)> when it's in the form of macro's ?
)
) Because preprocessor commands are acceptable in header files, because
) macros are all uppercase. ... <snip>

I fail to follow that logic. If I were to make the inline function all
uppercase, then it would be OK in your book ? And what does uppercase-ness
have to do with making a mess of the source tree ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Keith Thompson

Tom St Denis said:
So if I had a 1-5 [or so] liner function of code that I needed to
issue as fast as possible, I'd just write a macro and then the
compiler HAS to inline it [well ok, technically no, but it's highly
unlikely the compiler would put it in a function, call it, etc...].

Right, the compiler has to inline it -- even if a function call
would give you better performance for some reason.

Using "inline" lets the compiler choose the best way.
 
B

Ben Pfaff

Tom St Denis said:
Ok, but here's the question. What is the performance hit of this
being a normal function vs. inline? Is it actually called enough to
warrant this behaviour?

Possibly not. In which case I just move it to a .c file and
remove the "static inline" from two places. (This is less effort
than changing a macro into a function, for what it's worth.)

In this case it's questionable at best.
Perhaps, I see what you're saying. But if it's not a performance
hazard who cares if the function is small, don't inline it.

I agree. But in that case don't use a macro either.
 
W

Willem

Tom St Denis wrote:
)> > Because it's just not where code should go.  
)>
)> I see ... and a Macro is not code because .. ??
)
) Develop code how you want. I don't give a rats ass really. I'm
) trying to offer some helpful advice from my experience as a software
) developer. You're too prideful to either accept it or just graciously
) decline it is YOUR OWN PROBLEM.
)
) I'm not going to reply to you again in this thread.

In other words: "I don't care about your arguments, because I'm right."
All that means is that *you* are to prideful to concede any point.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
W

Willem

Tom St Denis wrote:
)> No, not at all.  For example, the following inline function
)> cannot be implemented as a macro (in an obvious way, at least)
)> without evaluating its argument more than once:
)>
)>     static inline bool ovsdb_type_is_set(const struct ovsdb_type *type)
)>     {
)>         return (type->value_type == OVSDB_TYPE_VOID
)>                 && (type->n_min != 1 || type->n_max != 1));
)>     }
)
) Ok, but here's the question. What is the performance hit of this
) being a normal function vs. inline? Is it actually called enough to
) warrant this behaviour?
)
)> Because the properties of a C function are much more predictable
)> than the properties of a C macro.  For example, when foo is
)> defined as a function, the argument type and return type are
)> well-defined.
)
) Perhaps, I see what you're saying. But if it's not a performance
) hazard who cares if the function is small, don't inline it.

Your arguments apply equally to macro's, so they are irrelevant to
this thread, which is about comparing macros with inline functions.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Ben Bacarisse

Tom St Denis said:
Last I checked ctags and grep don't work through #ifdef hell.

I don't see how finding the definition is easier for macros. #ifdef
hell can occur in either scenario -- inline functions and macros.
 
R

robertwessel2

Stephen Sprunk said:
Nick said:
VLAs don't have to be done on the stack do they?  Surely a compiler
could replace:
int bla(size_t sz) {
    char p[sz];
    /* do lots of things on p - reading that many characters from a file
    and hashing them, say */
    return result;
}
with
int bla(size_t sz) {
    char *p;
    p = malloc_with_somthing_on_failure(sz);
    /* do lots of things on p - reading that many characters from a file
    and hashing them, say */
    free(p);
    return result;
}
?
Such a simple example appears to comply with the as-if rule, but the
situation gets more complicated when there are multiple potential exits
from the function, including code paths not using "return".

Although I don't "do" C++, isn't that just what a C++ compiler must do
when an object with a destructor goes out of scope?  I've often thought
the ability to say "call this function on this object when it goes out
of scope" would be really useful, without going the whole OO hog.  It's
hard to come up with a nice syntax for it though.


Yes it does, although like everything in C++, it's not quite that
simple... For exceptions, they must destroy the objects on the way
out. Same for returns, of course. exit() cleans up static objects,
but not automatic or dynamically allocated ones. abort() cleans up
nothing. And the behavior of longjmp() are regards object cleanup is
undefined, and in most implementations longjmp() seems to do the usual
thing, and does *not* destroy any automatic objects (although I know
of at least one compiler that, optionally, allows longjmp to unwind
the stack and clean up objects).
 
I

Ian Collins

Tom said:
Tom said:
One additional effect of "inline" with the compiler that I use is
to suppress warnings about a function that is defined but never
used. This is presumably because "static inline" functions are
often defined in header files and thus may not be used by every
translation unit that includes them, whereas it is usually an
oversight if an ordinary "static" function is never called.
--
Ben Pfaffhttp://benpfaff.org
Code doesn't go in header files.
That is all.
Tom
Err, yes it CAN go there.
Where do you think inlines are defined?
Or Macros? All code.
Macros with all uppercase names can go in headers [obviously]. If the
function is complex/big enough that making it a macro is iffy then it
probably shouldn't be inlined anyways.
Leave the choice to the compiler. If you use a macro, the code will be
inline, if you use a function it will be inline if the compiler
considers it appropriate (unless you use any compiler specific options
to force the issue).

If it's ambiguous to whether the code would be best inlined or not you
probably should profile. Chances are the function belongs in a
proper .c file on its own.

An addition to Richard's comment, inline may be appropriate for some
platforms and not on others. One compiler I use (Sun cc) has a -native
switch that selects additional optimisations based on the host running
the compile, so even code that may not appear multi-platform might be.
I'm sure others do something similar.

It may also be an advantage not to have functions inlined in debug mode.
With macros, you don't have a choice.
 
D

Dik T. Winter

> > I can only think of one place where C++ mandates inline (in
> > the absence of an explicit "inline" and thats when the definition of a
> > member function is included in the class definition. =A0What are the
> > others?
>
> Reference to r7.1.2 [dcl.fct.spec] in the C++ standard confirms this.
> A function in C++ is never mandated to be inline. The keyword is only
> ever a hint, but member functions defined with a class definition are
> implicitly specified as if declared "inline".

So even in that case it is no more than a hint. So apparently C++ *never*
mandates an actual inline.
 
D

Dik T. Winter

>
> If what I'm doing can be implemented as a function, instead of as
> a macro, then I implement it as a function, because functions
> have fewer pitfalls than macros.

Consider 'max' with two integers.
 
D

Dik T. Winter

>
> The sort of thing you'd want to inline would be a short 3 line
> function anyways, so a macro would work just fine.

No. Only if each argument is used at most once.
 
B

Ben Pfaff

Dik T. Winter said:
Consider 'max' with two integers.

OK, I've considered it. I can think of several possible points
here. Which one are you trying to make?
 
K

Kaz Kylheku

Consider 'max' with two integers.

In C, you're best off with the macro.

Function solutions are clumsy because they constrain the left and right
operand to be of the same type, with a hard-coded return value.

The problem is that this is not how a max operator would behave, if it
were built into the language. C operators are polymorphic: their ersult
type is determined from the operand types, and, as well, the operands
are normalized (i.e. one converted to the type of the other).
The + operator can add a double and an int, a pointer and an unsigned
long, etc.

You can do max ``right'' with C++ template classes, functions and
partial specialization.
 
M

Michael Foukarakis

The "inline" directive slows down a program by bloating its code. With
today's CPUs programs go so fast that you can't see the bugs.
I lol'd.
To avoid that, you slow down your program using the "inline" directive. Hahaha!

This directive tells the compiler to replace a call to a function
with an insertion of the function's body at each call site.

This bloats the code in most cases. The bloated code slows down the
program that has to load more code into the cache from main memory.
Oh please stop!
Since most system busses go at 333MHZ or 666 MHZ at most, a CPU at
3GHZ must inserty wait states to wait until the RAM gives it the
new instructions to execute.
Sounds apocalyptic. If only there were more processes other than the
user's
program to execute so that we don't have to "inserty wait states".
I'll give
you a lol again.
If you want to make your program faster, avoid inline.
Wait until your senior programmer sees this.
Remember that
a call instruction is very small,
Not always. Think beyond x86/amd64.
and can be predicted in MOST cases
(unless it is a cal through a function pointer). This means that the
pipeline will keep full, and more code will fit in the code caches,
making the program go faster.
Consider the one-line function that returns 4. That's five
instructions on
amd64 together with preparing the stack and leave/ret. I urge you to
prove
your thesis that inlining THOSE will actually have an impact on my
instruction
cache. And then I might stop laughing.
 

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

Members online

No members online now.

Forum statistics

Threads
474,438
Messages
2,571,699
Members
48,796
Latest member
Greg L.
Top