Could someone explain "inline" for me?
Janus
Not quite. "inline" hints to the compiler to place the function *in-
line* with the caller, thus REMOVING the call altogether. It's a
redundant keyword nowadays as most compilers will automatically inline
things when its useful.
Tom
> On Dec 9, 7:45 am, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
>> janus <emekami...@gmail.com> writes:
>> >Could someone explain "inline" for me?
>>
>> Making a function an inline function suggests that
>> calls to the function be as fast as possible.
>
> Not quite. "inline" hints to the compiler to place the function *in-
> line* with the caller, thus REMOVING the call altogether.
There's nothing wrong with quoting the standard which is what Stefan
Ram did. One can imagine an architecture with executable "code
registers" where there might be a faster method than conventional
in-lining so the standard is wise to avoid saying what inline must
actually do.
> It's a
> redundant keyword nowadays as most compilers will automatically inline
> things when its useful.
Even then it is not quite redundant in that the compiler can diagnose
constraints when the function is marked as inline.
--
Ben.
> On Dec 9, 7:45 am, r...@zedat.fu-berlin.de (Stefan Ram) wrote:
>> janus <emekami...@gmail.com> writes:
>> >Could someone explain "inline" for me?
>>
>> Making a function an inline function suggests that
>> calls to the function be as fast as possible.
>
> Not quite. "inline" hints to the compiler to place the function *in-
> line* with the caller
Incorrect.
It hints to replace the call. Not inline *with* it.
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.
To avoid that, you slow down your program using the "inline" directive.
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.
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.
If you want to make your program faster, avoid inline. Remember that
a call instruction is very small, 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.
I have no idea what your distinction is. when you say "inline" it
will attempt to put the called function inside the callee, removing a
function call [thus no stack frames, etc to deal with].
Tom
"inline" can't really suggest anything else but to inline the called
function. Otherwise you still have to setup a stack frame and hit the
cost of calling a function.
> > It's a
> > redundant keyword nowadays as most compilers will automatically inline
> > things when its useful.
>
> Even then it is not quite redundant in that the compiler can diagnose
> constraints when the function is marked as inline.
I'm saying that in most modern compilers you will get function
inlining whether you use the keyword or not. So it's largely
academic.
It's like saying "auto" on stack variables...
Tom
On 12/09/2009 07:51 AM, jacob navia wrote:
> janus a �crit :
>> Hello All,
>>
>> Could someone explain "inline" for me?
>>
>> Janus
>
> 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.
>
> To avoid that, you slow down your program using the "inline" directive.
This is a ridiculous assertion.
> This directive tells the compiler to replace a call to a function
> with an insertion of the function's body at each call site.
And yet, oddly enough, this is roughly correct.
> 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.
And...back to the ridiculous.
> 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.
Really? I program PIC Microcontrollers where the bus speed is usually
around 4MHz. I'd suggest in the average house embedded devices such as
these far outnumber the system you describe.
As I believe Tom pointed out, it might be about as useful as `auto' but
I'm not convinced so many compilers are so intelligent.
The obvious cases where inline will likely be accepted by the compiler:
* the function is only called once
* the function body is smaller than the overhead created for the call
* the function is called in a tight loop where speed matters more than size.
> If you want to make your program faster, avoid inline. Remember that
> a call instruction is very small
Again, this assertion is completely false on many architectures.
--
Kyle A. York
Sr. Subordinate Grunt
BU formerly known as DS
It's a hint, not an instruction.
> 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.
Define "most cases". If the instruction sequence for the function body
is shorter than that required to call it, it shrinks the code.
> 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.
I don't have a figure for the ratio of embedded devices to desktops and
servers, but I'm sure it's high enough to invalidate that statement.
--
Ian Collins
IIRC, GCC will automatically inline "small" functions, but "inline"
tells it to inline the function regardless of size. The size threshold
can be changed via command-line flag, but IMHO that's not as clean.
Also, I think GCC does not output a standalone function body if the
function is declared "static inline" but does if the function is merely
declared "static", even if every call to the latter gets inlined due to
heuristics.
So, "inline" is not (yet?) completely useless like "auto" or "register".
S
--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
There are so many errors in this I don't even know where to start.
> janus a écrit :
<snip>
>> Could someone explain "inline" for me?
<snip>
> 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.
What bugs? This might have been a joke, in which case I think you
need a little work on your delivery.
> To avoid that, you slow down your program using the "inline" directive.
>
> 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.
>
> 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.
>
> If you want to make your program faster, avoid inline. Remember that
> a call instruction is very small, 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.
This runs counter to my experience. Maybe I used inline (and compilers
that inline automatically) when it is wise to do so, but in all the
cases I can remember, inlined code was faster (and occasionally smaller).
Maybe you can give an example where inlining slows down the code. I'd
like to see what sort of code leads you to this conclusion.
--
Ben.
I'd also be interested to hear this - my exprience accords with yours,
Ben. (Obviously inlining code will make the executable bigger, but it's
been a long time since disk space for binaries, or RAM to load them, was
an issue.)
On the other hand, I am a firm believer that loop unrolling can cause
the problems Jacob mentions, and for the reasons he describes. I suspect
that this is why (emprically) gcc's -O3 is almost always slower than
-O2.
Remember, boys and girls, this is from somenoe who thinks that the
stack-blowing idiocy known as variable length arrays is a good idea!
> To avoid that, you slow down your program using the "inline" directive.
Smart use of inline speeds up programs considerably. Some small
functinos can be replaced by an instruction sequence which is as short
as the function call.
I work on GNU/Linux running on MIPS. In userland, function calls are
gross. They have to ensure that the $gp register has the correct value,
load some offsets from the global offset table and then do an indirect
branch through the $t9 register.
For instance, the puts call in this:
#include <stdio.h>
int main(void)
{
puts("hello");
return 0;
}
turns into this:
Fetch the global pointer:
lui $28,%hi(%neg(%gp_rel(main)))
addu $28,$28,$25
addiu $28,$28,%lo(%neg(%gp_rel(main)))
Now go into the global offset table to figure
out where puts is, and begin the calculation
of where the string literal "hello" is:
lw $4,%got_page(.LC0)($28)
lw $25,%call16(puts)($28)
Save our caller's return address.
sd $31,8($sp)
Finally do the call.
jal $25
But not quite; in the branch delay slot, complete calculating the address of
the string literal:
addiu $4,$4,%got_ofst(.LC0)
Phew! It's definitely worth inlining a function that can be done in a few
instructions!
> This directive tells the compiler to replace a call to a function
> with an insertion of the function's body at each call site.
So does a function-like macro. Only the inline function is type safe.
> This bloats the code in most cases.
Can you put a number on this, like 75.3% of the cases?
What sampling method is is used, over what kind of data to arrive at the
statistic?
> The bloated code slows down the program that has to load more code into the
> cache from main memory.
What if the inline code is bloated, but it's in a tight loop that fits
nicely into the cache?
> If you want to make your program faster, avoid inline. Remember that
> a call instruction is very small
No it isn't; see MIPS code above.
> and can be predicted in MOST cases
> (unless it is a cal through a function pointer).
Typically, shared libraries always use indirect jumps.
> This means that the
> pipeline will keep full
See use of branch delay slot in MIPS code; something can be put into the
pipeline even though a branch is happening. (Though this is now part
of the instruction set architecture and behaves the same way regardless
of whether there actually is a branch delay slot, or how large it is;
if the hardware implementation has a two cycle stall in the pipeline for a
branch, you still get just one slot to fill).
Ah, this is obviously some strange usage of the phrase "not
quite" that I wasn't previously aware of. See ISO/IEC 9899:1999,
Section 6.7.4, paragraph 5, third sentence.
--
Eric Sosman
eso...@ieee-dot-org.invalid
it depends mostly on the size of the function...
inline is mostly useful for "one-liners", where the overhead of the call
will be larger than that of the code in the function...
but, for code much larger than this (such as code with loops or conditionals
and stuff), the use of inline is ill-advised... (since IME, the cost of a
function call is not usually THAT much higher than that of a loop iteration,
for example...).
except maybe on 64-bit Linux systems, where it remains as my running
hypothesis that their attempt at over-engineering the calling convention
will infact reduce call performance in the average case...
sadly, there is no real good way to test this hypothesis...
Yes, but the same set of instructions are being executed whether a
function is inlined or not: the only difference is whether or not
there's a function call thrown into the mix. So as much of the program
will fit into the instruction cache either way. There might be tiny
gains if the inlined code can map into the same cache line while the
non-inlined code has to be fetched fresh, but this difference will be
eliminated in subsequent calls to the function -- and we're mostly
talking about the gain being in tight loops here where the same function
gets called many times.
Apart from saving function call overhead, inlining might also give the
optimizer more chance to reuse common subexpressions or the like, so
that's another possible benefit. But better use of cache? I don't see
it.
agreed...
granted, WRT loop unrolling, it may depend in large part on the size of the
loop body and number of iterations, where a large number of iterations, or a
large loop body, are likely to hurt things much more than a small loop body
with a small number of iterations.
granted, in general I am not in favor of loop unrolling, since in the cases
it is actually likely to help, I can just as easily unroll by hand, and not
have the compiler unroll the bigger loops (which are likely to just make
things slower...).
granted, micro-optimization is a touchy issue, and cache-hits/misses more
so, and so I generally don't bother, and try to instead just let the
profiler tell me where performance is needed...
No, not obviously. Sometimes the function call sequence is actually
longer than the inline code.
Suppose I had a function like this in a shared library on MIPS:
int get_foo_count(struct bar *bar)
{
return bar->foo_count;
}
calling this will be almost certainly longer than just doing the access
directly with inline code (macro or inline function).
See, computing the address of a function in a shared library and calling
it is more complicated than accessing a structure member.
Even if the function is not in a shared library, it may still be
more instructions to do the call. Suppose I add the call into a leaf
function. Now that function becomes a caller to a callee, and has
new responsibilities: namely saving all of the caller-saved registers!
Whatever it is, multiply it by at least 4. I know the portable device
I have in my hands as we speak has at least _6_ ARM cores on it, each
programmed in C.
In addition:
For most PCs with bluetooth, add one to the embedded device tally.
For most PCs with WLAN, add another one to the embedded device tally.
For most PCs with ethernet, add another one to the embedded device tally.
In fact, it's not even going to be close, is it?
Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
The "auto" keyword is completely useless (except perhaps as
documentation); it can only specify something that the compiler *must*
do in the absence of the keyword. It was useful in older versions of C,
where
auto x;
static y;
declared x and y as objects of type int (even there I'd prefer to
declare them as "int" explicitly, making the "auto" keyword
redundant).
The "register" keyword, on the other hand, is at least potentially
meaningful. The common wisdom is that the compiler can always do
a better job of register allocation than the programmer can, but
I'm not sure that's entirely true. It also has a semantic effect:
it forbids taking the address of the object. Even if the compiler
doesn't choose to store the object in a register, knowing that
its address is never computed might be helpful for optimization.
(Though since "register" can be applied only to objects with block
scope, a reasonably clever compiler should be able to determine
that for itself.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
An effect I've not seen mentioned here is that expanding
a function body in-line may allow some parts to be "executed"
at compile time.
inline void foo(int which) {
switch (which) {
case 0: code-for-0; break;
case 1: code-for-1; break;
...
}
}
An in-line call to foo(1) might turn into code-for-1 all by
itself, with all the other cases -- the whole switch, in
fact -- removed as dead code. Not only do you eliminate the
time to get to the function and back again, but you may also
eliminate or simplify some of the code inside the function.
--
Eric Sosman
eso...@ieee-dot-org.invalid
Not necessarily the case. There exist systems on which it is possible
for the cost of calling a function to be essentially zero if the function
meets certain criteria -- in which case, the compiler might choose to
tweak the implementation of the function to meet those criteria, then continue
emitting calls to it. If the calls are smaller than the function body,
but the call overhead is functionally zero, this may even IMPROVE performance
in some cases.
So it really is just "please be fast".
> I'm saying that in most modern compilers you will get function
> inlining whether you use the keyword or not. So it's largely
> academic.
True.
> It's like saying "auto" on stack variables...
Not really. That definitively changes nothing, where as specifying inline
may cause a compiler to try to inline (or otherwise speed up) a function
it otherwise might not have.
-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
It's for people who don't like macros.
--
pete
CLC drone,
You might want to acquaint yourself with this idea of ``context'', which
has to do with why there is a first sentence, and a second sentence, and
possibly fourth one, and so on.
Something ripped out of context is, in fact, ``not quite'' that
thing in its proper context.
In order to fetch arbitrary memory, the 6502 had to spend twice as
long interfacing with the address bus than it did when accessing
zero page RAM. So the actual fast memory was only 256 bytes.
Just because you do not like the fact that a group of people often
agree with each other, and often disagree with you does not make
them drones. If you are unable to enter into polite discourse with
those who show a preference for such, then perhaps you should
consider not partaking in any discourse at all.
> You might want to acquaint yourself with this idea of ``context'', which
> has to do with why there is a first sentence, and a second sentence, and
> possibly fourth one, and so on.
>
> Something ripped out of context is, in fact, ``not quite'' that
> thing in its proper context.
And precisely which bit of the first, second, and fourth sentences
in any way modify the payload of the third sentence? If none, then
why are you wasting people's time drawing their attention to them?
Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
> LocalWords: Devany
Oh. The. Irony.
Phil "the Psycho" Carmodey lecturing other people on politeness - I've
heard it all now.
A quick test (of an inline function more complicated than that,
but still with complile-time calculation of the return value
indicates that gcc 2.7.2 was doing this even back in 1995. I'm
pretty sure Borland was not able to do it in 1993, and wonder
when this intelligent inlining became mainstream. Anyone
got a 2.5, 2.4, or earlier, gcc to hand?
Your buddy Heathfield is still using one of those versions as his main
compiler.
Inline will be a bad choice in general when then size of the inlined function's body
is bigger than the calling sequence of the normal call. I.e. when there is an
increase in the size of the code.
What is important to notice in this context is that the speed of
RAM is VERY slow compared to the speed of the in-cache RAM and
the speed of the processor. The more code you get into the code cache
the faster your program will run.
Inlining, specially in C++ is a nightmare since it tends to be used
too much, and in situations where it shouldn't be used at all. C++
mandates inline in many contexts, and in the company where I work
this bloats the code enormously.
Obviously I can't send you the 40-50MB executable for you to
inspect it, sorry.
lcc-win optimizes only for code size, and using only this optimization,
speed has been greatly increased.
jacob
Sure, in this cases inline can be beneficial, but this cases
tend to be used in C++ more than in C.
> Even if the function is not in a shared library, it may still be
> more instructions to do the call. Suppose I add the call into a leaf
> function. Now that function becomes a caller to a callee, and has
> new responsibilities: namely saving all of the caller-saved registers!
So what?
The point is if the code gets bigger or not. That is the main criteria.
To call it "stack blowing" is the contarry of the effect of the VLA.
But that is another discussion.
What your example of that old RISC architecture proves is just
that in some circumstances inline can be useful.
My post was directed at provoking a discussion and showing an
alternative way of looking at some established "dogmas".
jacob
Great!
So, do not start at all.
If you use even an old CPU, it is highly unlikely that will be
less than 1GHZ. RAM in embedded devices is way slower than
workstations RAM too, so the ration should stay the same or even worst
than workstations.
Sure, and in a PIC with 128 bytes of RAM you want
to use inline
GREAT pal! GO ON LIKE THIS. Do not fear being
spotted as somebody the writes before turning on the brain
:-)
That's a rather extreme claim. (Though the phrase "in general" is
ambiguous; it can mean either "usually" or "always". Which did you
mean?)
Here's a somewhat contrived counterexample. Suppose you have a tight
inner loop, executed bajillions of times, containing a function call.
If the inlined code for the function is smaller than the calling
sequence, then inlining almost certainly makes sense; it saves both
time and space.
But suppose inlining the function increases (say, doubles or triples)
the size of the code for the loop, but the entire loop *still* fits in
cache. In that case, I would think that inlining would improve speed
at the cost of some increase in code size.
[...]
> lcc-win optimizes only for code size, and using only this optimization,
> speed has been greatly increased.
Ok, but I wonder if you could get even better speed with a slightly
less lopsided optimization strategy.
Hypocrite
�noun
1. a person who pretends to have virtues, moral or religious beliefs,
principles, etc., that he or she does not actually possess, esp. a
person whose actions belie stated beliefs.
2. a person who feigns some desirable or publicly approved attitude,
esp. one whose private life, opinions, or statements belie his or her
public statements.
> Ben Bacarisse a écrit :
>> Maybe you can give an example where inlining slows down the code. I'd
>> like to see what sort of code leads you to this conclusion.
>>
>
> Inline will be a bad choice in general when then size of the inlined function's body
> is bigger than the calling sequence of the normal call. I.e. when there is an
> increase in the size of the code.
This is just an assertion. I was hoping you could post a C example.
maybe I have always used machines where inlining pays greater
dividends.
In one example I've just tried, the inlined version is always faster
than the non-lined but the inlined code is also smaller at higher
optimisation settings.
> What is important to notice in this context is that the speed of
> RAM is VERY slow compared to the speed of the in-cache RAM and
> the speed of the processor. The more code you get into the code cache
> the faster your program will run.
Empirical evidence of faster code when inlining is used needs to be
explained. If you gave me an example of code that was slower, I might
see what the difference is. You've formed this opinion for a reason
and like to know why you've reached a different conclusion from me.
I'll note also that the gcc implementors seem to think that inlining
helps. gcc does it even when not explicitly requested in the code
meaning I've had to work hard to prevent it in order to do some
timings.
> Inlining, specially in C++ is a nightmare since it tends to be used
> too much, and in situations where it shouldn't be used at all. C++
> mandates inline in many contexts, and in the company where I work
> this bloats the code enormously.
>
> Obviously I can't send you the 40-50MB executable for you to
> inspect it, sorry.
I don't want a non C example. Do you have one in C or does your
remark only apply to languages like C++ compilers?
> lcc-win optimizes only for code size, and using only this optimization,
> speed has been greatly increased.
That does not show that is could not be faster still if you included
inlining. I am not saying it would be, of course, but I'd like an
example that I can test to see where the problem really is.
--
Ben.
Not if it's for an embedded application.
> RAM in embedded devices is way slower than
> workstations RAM too, so the ration should stay the same or even worst
> than workstations.
Definitely not always. Sometimes people pick fast RAM and slow
processors (sometimes even underclocking the processor) so that RAM
access is single cycle. This can help minimise power consumption for a
given speed of processing since you are powering the devices just for
work and not for sitting in wait states.
--
Flash Gordon
possibly the case, but I am not sure this is likely to be as
significant/frequent in practice...
> --
> Eric Sosman
> eso...@ieee-dot-org.invalid
I use both, but which is used depends more on the specific behaviors...
a notable weak point of using macros is that they may end up evaluating the
arguments multiple times, which can either break or foul up some use cases,
as well as slowing down others.
so, there are reasons one might want the semantics of avoiding multiple
evaluations, while still having an overhead similar to that of a macro.
> --
> pete
I don't personally implement VLAs, mostly since I don't use them, and
secondly because they would be a problem to implement with my current
compiler (if they are to be, in fact, located on the stack).
part of the reason for this is that my compiler generally keeps track of
where everything is on the stack, and so depends on having the stack layout
fixed at compile time. variable-length objects would pose a problem in that
one can no longer statically calculate all their stack offsets.
>> To avoid that, you slow down your program using the "inline" directive.
>
> Smart use of inline speeds up programs considerably. Some small
> functinos can be replaced by an instruction sequence which is as short
> as the function call.
>
> I work on GNU/Linux running on MIPS. In userland, function calls are
> gross. They have to ensure that the $gp register has the correct value,
> load some offsets from the global offset table and then do an indirect
> branch through the $t9 register.
>
> For instance, the puts call in this:
>
> #include <stdio.h>
>
> int main(void)
> {
> puts("hello");
> return 0;
> }
>
> turns into this:
>
>
> Fetch the global pointer:
>
> lui $28,%hi(%neg(%gp_rel(main)))
> addu $28,$28,$25
> addiu $28,$28,%lo(%neg(%gp_rel(main)))
>
> Now go into the global offset table to figure
> out where puts is, and begin the calculation
> of where the string literal "hello" is:
>
> lw $4,%got_page(.LC0)($28)
> lw $25,%call16(puts)($28)
>
> Save our caller's return address.
>
> sd $31,8($sp)
>
> Finally do the call.
>
> jal $25
>
> But not quite; in the branch delay slot, complete calculating the address
> of
> the string literal:
>
> addiu $4,$4,%got_ofst(.LC0)
>
> Phew! It's definitely worth inlining a function that can be done in a few
> instructions!
>
it is not so good on x86-64 either, since a function call may involve:
having to spill any values in any caller-save/scratch registers;
having to get arguments into the correct registers (this part itself a
little "painful" with SysV);
doing the call;
maybe having to reserve stack space and spill the arguments (almost
invariable with any non-leaf functions, given they are passed in scratch
registers);
...
>> This directive tells the compiler to replace a call to a function
>> with an insertion of the function's body at each call site.
>
> So does a function-like macro. Only the inline function is type safe.
>
>> This bloats the code in most cases.
>
> Can you put a number on this, like 75.3% of the cases?
>
> What sampling method is is used, over what kind of data to arrive at the
> statistic?
>
yeah, I think he is thinking most inline functions are large...
this is maybe about the same as me thinking that most functions are non-leaf
functions...
but, then again, I have written enough code to be almost certain that this
is the case:
a rare minority of code is leaf functions;
very little is to say that it is the leaf functions which will be eating the
running time.
>> The bloated code slows down the program that has to load more code into
>> the
>> cache from main memory.
>
> What if the inline code is bloated, but it's in a tight loop that fits
> nicely into the cache?
>
>> If you want to make your program faster, avoid inline. Remember that
>> a call instruction is very small
>
> No it isn't; see MIPS code above.
>
yeah.
depends on the arch...
personally I suspect that function calls are cheaper on x86 than on x86-64
(SysV and Win64), since there are so few registers that there is not nearly
so much worry about the cost of spills.
>> and can be predicted in MOST cases
>> (unless it is a cal through a function pointer).
>
> Typically, shared libraries always use indirect jumps.
>
yeah, or at least with ELF and friends...
with PE/COFF, only non-local calls are indirect (or at least on x86 and
x86-64, I know little about MIPS...).
>> This means that the
>> pipeline will keep full
>
> See use of branch delay slot in MIPS code; something can be put into the
> pipeline even though a branch is happening. (Though this is now part
> of the instruction set architecture and behaves the same way regardless
> of whether there actually is a branch delay slot, or how large it is;
> if the hardware implementation has a two cycle stall in the pipeline for a
> branch, you still get just one slot to fill).
ok.
... unless the particular arguments being passed to the inline function
allow the compiler to eliminate most of the function body as dead code.
> What is important to notice in this context is that the speed of
> RAM is VERY slow compared to the speed of the in-cache RAM and
> the speed of the processor. The more code you get into the code cache
> the faster your program will run.
All of that is true, but the function body has to be loaded into cache
whether or not it's inlined. The _only_ time this matters, then, is if
the parent function calls the leaf function multiple times, each call is
inlined, and there are not enough dead code or common code eliminations
to make up for the increased code size.
S
--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
Well the fastest of our layer 3 switching products uses 800MHz PowerPC,
most use 500 or 666MHz parts. They also use standard PC DDR2 RAM. So
wrong on both counts.
--
Ian Collins
Why? Some of us prefer small functions in C as well. Yes the style
used to be more common in C++, but modern C compilers have caught up
with C++ compiler's ability to automatically in line appropriate functions.
Do remember the inline keyword is little more than a waste of pixels
these days.
>> Even if the function is not in a shared library, it may still be
>> more instructions to do the call. Suppose I add the call into a leaf
>> function. Now that function becomes a caller to a callee, and has
>> new responsibilities: namely saving all of the caller-saved registers!
>
> So what?
>
> The point is if the code gets bigger or not. That is the main criteria.
On some platforms that may gain you speed, on other it may not.
--
Ian Collins
> Kaz Kylheku a écrit :
>> On 2009-12-09, jacob navia <ja...@spamsink.net> wrote:
>>> janus a écrit :
>>>> Hello All,
>>>>
>>>> Could someone explain "inline" for me?
>>>>
>>>> Janus
>>> 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.
>>
>> Remember, boys and girls, this is from somenoe who thinks that the
>> stack-blowing idiocy known as variable length arrays is a good idea!
>>
> I think that VLAs are a good construct proposed by the C standard.
> I have (in comp.std.c++) argued that it decreases the stack usage
> since you use only what you need and to some arbitrary maximum size.
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;
}
?
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu
> >> If you are unable to enter into polite discourse with those who show a
> >> preference for such, then perhaps you should consider not partaking in
> >> any discourse at all.
>
> > Oh. The. Irony.
>
> > Phil "the Psycho" Carmodey lecturing other people on politeness - I've
> > heard it all now.
>
> Hypocrite
> –noun
> 1. a person who pretends to have virtues, moral or religious beliefs,
> principles, etc., that he or she does not actually possess, esp. a
> person whose actions belie stated beliefs.
>
> 2. a person who feigns some desirable or publicly approved attitude,
> esp. one whose private life, opinions, or statements belie his or her
> public statements.
interesting. The term is often misused then. The charge of hypocrisy
is often levelled at people who offer advice that they themselves
don't follow whilst the actual meaning is more subtle.
> >> 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.
>
> > Really? I program PIC Microcontrollers where the bus speed is usually
> > around 4MHz. I'd suggest in the average house embedded devices such as
> > these far outnumber the system you describe.
>
> Sure, and in a PIC with 128 bytes of RAM you want
> to use inline
so there are uses for it?
> GREAT pal! GO ON LIKE THIS. Do not fear being
> spotted as somebody the writes before turning on the brain
why so rude?
> :-)
the smiley doesn't help
> C++ mandates inline in many contexts, and in the company where
> I work this bloats the code enormously.
Really? 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. What are the
others?
> Hypocrite
> –noun
> 1. [Definitions elided].
Gee. Thats interesting. Would you apply that definition to someone
who excoriates others for making personal attacks, and then does the
same themselves?
> Smart use of inline speeds up programs considerably. Some small
> functinos can be replaced by an instruction sequence which is as short
> as the function call.
I often think Kaz's posts are unnecessarily abrasive, but for coining
the word functino to mean "small function" I can forgive a great deal.
I do hope that word becomes accidentally adopted.
Tony
Was he using it prior to October 2000? [1]
My usage of "functino" to mean "pointer to function" on Usenet goes
back to that date. I think of functinos as being very, very small and
very, very fast (which is strange, since they don't actually move at
all).
Using Google's utterly inadequate searching, the first use I can find
of "functino" in comp.lang.c is Rod P, in June 2000 - apparently an
unintended typographical error. Second use: Marco Soeima in October
2000, again apparently a typo. Third use: me, a few days after that:
Msg ID: <39E2CE02...@antlimited.com>
"You can convert from many things to many other things, correctly,
without casting, because of the promotion rules. In the particular
case of pointers, you're right, but it's conversion from and to void
*, not void. (And you have to be really careful with functinos+.)
[+ "functino" - n. (funk - teen' - oh) pointer to function.]"
I claim first intentional use.
[1] As a matter of fact, I was using the term in the above sense for
at least three or four years before I started using Usenet - 1996 or
1997, I believe. But the above quote is the earliest independently
verifiable usage that I can produce.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
> 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. What 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".
Settling the question (either way) would require a good
deal of research. Still, my un-researched impression is that
compilers are pretty aggressive optimizers nowadays, and that
an inlined function body might afford the optimizer more room
to maneuver than the "outlined" version. The compiler working
on an inlined call has information not available to a compiler
building code for a general case. And even if there are no
shortcuts from dead code elimination or from folding in of
known-to-be-constant arguments, there's the possibility of
"cross-talk" between the function body and the caller that
embeds it: Common sub-expression elimination, use of registers
to cache values used in both caller and callee, ...
The opportunities are certainly present. The extent to
which they're used is situational -- and is the hard part to
assess in a general way.
--
Eric Sosman
eso...@ieee-dot-org.invalid
Q: without the "inline", is the compiler free to compile it inline
anyway? I see no reason why not.
In which case the aggressive nature of compilers and the fact it needn't
bother even inlining it anyway makes the entire conversation 100%
platform dependant.
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
Code doesn't go in header files.
That is all.
Tom
Inline functions MUST be written in header files...
Err, yes it CAN go there.
Where do you think inlines are defined?
Or Macros? All code.
> Tom St Denis a écrit :
>> On Dec 9, 3:11 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>>> 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.
<snip sig>
>> Code doesn't go in header files.
In general I agree, but inline functions are, to me, an obvious
exception.
<snip another sig>
> Inline functions MUST be written in header files...
They often are, but why do you say the must be?
--
Ben.
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".
The easiest way to get "automatic storage duration" is to put a VLA in
the same place as all other objects of "automatic storage duration",
i.e. the stack (on machines that have such). In a sense, VLAs are a
more portable way of providing alloca().
Yeah, but you neglected to respond to the excellent counter-arguments to
that.
If it's trivial enough that being in a header makes sense make it a
macro and uppercase.
Nothing worse than sorting through 250 unsorted .c and .h files trying
to find some random function with a mixed case name because some
jackass thought it was a good idea (bonus points for #ifdef hell).
Tom
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.
Tom
On 12/09/2009 02:58 PM, jacob navia wrote:
> kyle york a �crit :
>>> 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.
>>
>> Really? I program PIC Microcontrollers where the bus speed is usually
>> around 4MHz. I'd suggest in the average house embedded devices such as
>> these far outnumber the system you describe.
>
> Sure, and in a PIC with 128 bytes of RAM you want
> to use inline
Your wristwatch has a 1GHz pentium? You change the battery every 15 minutes?
> GREAT pal! GO ON LIKE THIS. Do not fear being
> spotted as somebody the writes before turning on the brain
No idea what you're getting at here, apparently in your world all
computers are on desks and run Windows.
--
Kyle A. York
Sr. Subordinate Grunt
BU formerly known as DS
> On Dec 10, 9:45 am, jacob navia <ja...@nospam.org> wrote:
>> Tom St Denis a crit :
>>
>> > On Dec 9, 3:11 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> >> 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
>>
>> Inline functions MUST be written in header files...
>
> If it's trivial enough that being in a header makes sense make it a
> macro and uppercase.
Don't be so silly. A macro is not the same thing in any shape or form.
>
> Nothing worse than sorting through 250 unsorted .c and .h files trying
> to find some random function with a mixed case name because some
> jackass thought it was a good idea (bonus points for #ifdef hell).
>
> Tom
Nothing worse than someone using an extreme case to support a rather
silly thought.
> If it's trivial enough that being in a header makes sense make it a
> macro and uppercase.
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.
> Nothing worse than sorting through 250 unsorted .c and .h files trying
> to find some random function with a mixed case name because some
> jackass thought it was a good idea (bonus points for #ifdef hell).
Why don't you use an editor that can jump right to a definition
based on its name? By using inferior tools you indeed are
wasting your time.
--
"Large amounts of money tend to quench any scruples I might be having."
-- Stephan Wilms
> If you want to make your program faster, avoid inline. Remember that
> a call instruction is very small, and can be predicted in MOST cases
> (unless it is a cal through a function pointer).
If the only benefit of "inline" is likely to be elimination of the
function call overhead, don't use it.
OTOH, inlining code into specific contexts can enable various
optimisations which would be precluded if the compiler has to generate
a function which can be called from anywhere.
The most obvious example of this is when the inlined function is called
within a loop, as it allows the use of loop induction (aka strength
reduction) optimisations on the function's body.
From my experience the sort of things that are short enough to warrant
inlining and tossing in a header are short enough that they can be
done via macros. I've never had occasion to really put a full C
function as "static inline" inside header files.
> > Nothing worse than sorting through 250 unsorted .c and .h files trying
> > to find some random function with a mixed case name because some
> > jackass thought it was a good idea (bonus points for #ifdef hell).
>
> Why don't you use an editor that can jump right to a definition
> based on its name? By using inferior tools you indeed are
> wasting your time.
Last I checked ctags and grep don't work through #ifdef hell.
Tom
The sort of thing you'd want to inline would be a short 3 line
function anyways, so a macro would work just fine. If the body of the
function is longer than the percentage of time taking from the call/
stack frame setup is minimal and making it inlined is near pointless.
> > Nothing worse than sorting through 250 unsorted .c and .h files trying
> > to find some random function with a mixed case name because some
> > jackass thought it was a good idea (bonus points for #ifdef hell).
>
> > Tom
>
> Nothing worse than someone using an extreme case to support a rather
> silly thought.
I've never have had the need to put a "static inline" function in a
header, and the few times I had a piece of code that was short enough
to warrant forced inlining I just made it a macro.
Sometimes the macro route works better if you're doing something
involving an asm() block. GCC at least can better optimize around them
[register selection, etc] if the code being "called" is actually just
part of the function to start with as opposed to something you call
from a C language point of view...
Tom
> On Dec 10, 12:40 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> Tom St Denis <t...@iahu.ca> writes:
>>
>> > If it's trivial enough that being in a header makes sense make it a
>> > macro and uppercase.
>>
>> 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.
>
> From my experience the sort of things that are short enough to warrant
> inlining and tossing in a header are short enough that they can be
> done via macros. I've never had occasion to really put a full C
> function as "static inline" inside header files.
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?
--
Ben Pfaff
http://benpfaff.org
ctags and grep suck compared to most frameworks in competent
code editors. However I never found a case where #ifdefs affected ctags in such
a way that you could not find what you wanted.
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).
--
Ian Collins
It is.
> In which case the aggressive nature of compilers and the fact it needn't
> bother even inlining it anyway makes the entire conversation 100%
> platform dependant.
Correct.
--
Ian Collins
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. If you can keep it
organized all the power to you, but I've been in a few big name shops,
and seem a handful of small shops, and from what I've seen personally,
it usually leads to disasters.
At the very least it should be in a localized header file, e.g. a
typical tree might resemble
src/headers
src/foo
src/bar
src/stuff
If say the files in src/foo/ need an inline function put it in a
header in say src/foo or src/foo/headers as opposed to src/headers...
I'd also challenge most people who use the "inline" keyword to profile
their code and see where time is spent. It's a common mistake for
inexperienced [not saying you are...] developers to outsmart the
situation and not actually profile. I saw a once-called function at
startup be "hella optimized" in really confusing mix of C++/asm all to
shave much less than 1ms off startup time on a server application.
The function was called once during initialization and never seen
again, yet the guy insisted on 3000 lines of template/asm code to
optimize the situation.
Tom
Another, possibly more common, case is optimisation of register usage.
--
Ian Collins
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.
> Nothing worse than sorting through 250 unsorted .c and .h files trying
> to find some random function with a mixed case name because some
Really; not a single thing worse, Tom?
No grep? No ctags? No mkid? No cscope?
Inline functions provide safety over macros.
/* 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; }
/* this converts anything to ``foo *'' that can be,
including integers and, on most compilers,
function pointers, without any cast at the
call site. */
#define the_foo(b) ((foo *) (b))
One possible screwup:
f = the_foo(fun); /* oops should have been the_foo(fun()). */
I mention this one because I recently had macros of this type in a new C
program, and made something similar to the above boo boo.
I wisened up and turned them into inline functions.
> On Dec 10, 1:16 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> 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.
Here's a decent example of the sort of thing that I would
typically put in a header file:
http://openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=lib/ovsdb-types.h;h=78d76c97e5d68e167a551ca3058ed4cb349e67bd;hb=next
Here's another, although really the tag_set_intersects() function
is probably too large:
http://openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=lib/tag.h;h=f645dc91a16616199b25d96df7b93dc118e97947;hb=next
/* Expands to a void expression that checks that POINTER is an
expression whose type is a qualified or unqualified version of
a type compatible with TYPE (a pointer type) and, if not,
causes a compiler warning to be issued (on typical compilers).
Examples:
int *ip;
const int *cip;
const int **cipp;
int ***ippp;
double *dp;
// None of these causes a warning:
CHECK_POINTER_HAS_TYPE (ip, int *);
CHECK_POINTER_HAS_TYPE (ip, const int *);
CHECK_POINTER_HAS_TYPE (cip, int *);
CHECK_POINTER_HAS_TYPE (cip, const int *);
CHECK_POINTER_HAS_TYPE (dp, double *);
CHECK_POINTER_HAS_TYPE (dp, const double *);
CHECK_POINTER_HAS_TYPE (cipp, const int **);
CHECK_POINTER_HAS_TYPE (cipp, const int *const *);
CHECK_POINTER_HAS_TYPE (ippp, int ***);
CHECK_POINTER_HAS_TYPE (ippp, int **const *);
// None of these causes a warning either, although it is unusual to
// const-qualify a pointer like this (it's like declaring a "const int",
// for example).
CHECK_POINTER_HAS_TYPE (ip, int *const);
CHECK_POINTER_HAS_TYPE (ip, const int *const);
CHECK_POINTER_HAS_TYPE (cip, int *const);
CHECK_POINTER_HAS_TYPE (cip, const int *const);
CHECK_POINTER_HAS_TYPE (cipp, const int **const);
CHECK_POINTER_HAS_TYPE (cipp, const int *const *const);
CHECK_POINTER_HAS_TYPE (ippp, int ***const);
CHECK_POINTER_HAS_TYPE (ippp, int **const *const);
// Provokes a warning because "int" is not compatible with "double":
CHECK_POINTER_HAS_TYPE (dp, int *);
// Provoke warnings because C's type compatibility rules only allow
// adding a "const" qualifier to the outermost pointer:
CHECK_POINTER_HAS_TYPE (ippp, const int ***);
CHECK_POINTER_HAS_TYPE (ippp, int *const**);
*/
#define CHECK_POINTER_HAS_TYPE(POINTER, TYPE) \
((void) sizeof ((TYPE) (POINTER) == (POINTER)))
/* Given expressions A and B, both of which have pointer type,
expands to a void expression that causes a compiler warning if
A and B are not pointers to qualified or unqualified versions
of compatible types.
Examples similar to those given for CHECK_POINTER_HAS_TYPE,
above, can easily be devised. */
#define CHECK_POINTER_COMPATIBILITY(A, B) ((void) sizeof ((A) == (B)))
/* Equivalent to casting POINTER to TYPE, but also issues a
warning if the cast changes anything other than an outermost
"const" or "volatile" qualifier. */
#define CONST_CAST(TYPE, POINTER) \
(CHECK_POINTER_HAS_TYPE (POINTER, TYPE), \
(TYPE) (POINTER))
/* Given POINTER, a pointer to the given MEMBER within structure
STRUCT, returns the address of the STRUCT. */
#define UP_CAST(POINTER, STRUCT, MEMBER) \
(CHECK_POINTER_COMPATIBILITY (&((STRUCT *) 0)->MEMBER, POINTER), \
(STRUCT *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER)))
So why are you not against putting code in header files,
when it's in the form of macro's ?
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
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.
Tom
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. When I want to look for a function, it should be in
a .c file in a well sorted directory structure.
I guess my real problem is people who tend to do that tend to violate
all sorts of other decent coding practices too..
> Here's a decent example of the sort of thing that I would
> typically put in a header file:
> http://openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=lib/...
Those are all one-liners which are perfectly well suited for being
macros.
> Here's another, although really the tag_set_intersects() function
> is probably too large:
> http://openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=lib/...
Same with those.
Why is
static inline int foo(int a) { return a + 3; }
So much simpler than
#define FOO(a) ((a) + 3)
?
At least now when I include foo.h I don't get some function I may not
call... and because it's all uppercase I know to search for FOO in a
header file.
Tom
Don't macros also make debugging more of a mess at times too?
> On Dec 10, 1:41 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> Tom St Denis <t...@iahu.ca> writes:
>>
>> > On Dec 10, 1:16 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> >> 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 .. ??
Because preprocessor commands are acceptable in header files, because
macros are all uppercase. If you absolutely want your function
inlined, "inline" is actually NOT the way to go. It doesn't force the
compiler to do anything. It could straight up ignore it and just call
the function instead.
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...].
Tom
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.
Tom
LOL. Yeah right.
> not uncommon to have platform specific branches of code that include
> platform specific macros.
And? How does that stop ctags working albeit ugly?
Nothing you said there makes it any easier to use macros over inlines in
terms of code navigation.
In fact, I'm not even sure where your ctags and and grep comment was
relevant. Inferior tools are inferior tools regardless of how you
prefer macros over inlines.
>
> Tom
> On Dec 10, 1:52 pm, Willem <wil...@stack.nl> wrote:
>> Tom St Denis wrote:
>>
>> ) 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. ... <snip>
>>
>> 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. If you absolutely want your function
But they are not.
And profiling does what in the case of multi platform code?
> Nick wrote:
>> 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.
> The easiest way to get "automatic storage duration" is to put a VLA in
> the same place as all other objects of "automatic storage duration",
> i.e. the stack (on machines that have such). In a sense, VLAs are a
> more portable way of providing alloca().
Oh yes, I'm challenging the necessity, rather than the likelihood.
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu
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
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.
> > Nothing worse than sorting through 250 unsorted .c and .h files trying
> > to find some random function with a mixed case name because some
>
> 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
> On Dec 10, 1:41 pm, Ben Pfaff <b...@cs.stanford.edu> wrote:
>> 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. 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.
>> Here's a decent example of the sort of thing that I would
>> typically put in a header file:
>> http://openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=lib/...
>
> 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.
--
"You call this a *C* question? What the hell are you smoking?" --Kaz
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.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
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